SQL 电子邮件验证(无正则表达式)
Posted
技术标签:
【中文标题】SQL 电子邮件验证(无正则表达式)【英文标题】:TSQL Email Validation (without regex) 【发布时间】:2010-09-18 19:01:50 【问题描述】:好的,有一百万个正则表达式可用于验证电子邮件地址,但是可以将一些基本的电子邮件验证集成到 Sql Server 2005 的 TSQL 查询中怎么样?
我不想使用 CLR 过程或函数。直接 TSQL。
有人已经解决了这个问题吗?
【问题讨论】:
Sql script to find invalid email addresses 的可能重复项 【参考方案1】:非常基本是:
SELECT
EmailAddress,
CASE WHEN EmailAddress LIKE '%_@_%_.__%'
AND EmailAddress NOT LIKE '%[any obviously invalid characters]%'
THEN 'Could be'
ELSE 'Nope'
END Validates
FROM
Table
这匹配所有中间有一个@,前面至少有一个字符,后跟至少两个,一个点,至少两个TLD。
你可以编写更多的LIKE
模式来做更具体的事情,但是你永远无法匹配所有可能是电子邮件地址的东西,同时又不会漏掉不是的东西。即使使用正则表达式,你也很难做到正确。此外,即使根据 RFC 的字母进行匹配,也会匹配大多数电子邮件系统不会接受/使用的地址结构。
无论如何,在数据库级别执行此操作可能是错误的方法,因此如上所述的基本完整性检查可能是您可以获得的最佳性能,并且在应用程序中执行此操作将为您提供更大的灵活性。
【讨论】:
是的,我已经在代码中为我准备了正则表达式,但我需要对包含数百万封电子邮件的表格进行报告并得出汇总数据。 了解你拥有的基础数据,你可能会想出比我一开始建议的更具体和更合适的东西,但你永远不会得到它“正确”,因为使用了这个词在算法理论中。 我看到你添加了“不像'%[任何明显无效的字符]%”。根据我对规范的了解,我不确定键盘上实际上是否有任何键在技术上不能被解释为地址中的某处有效。 这取决于您的键盘。我的有'ö','ä','ü'和'ß',无论如何这些都是无效的。更一般地说,例如不允许使用尖括号,并且不胜枚举。 非常感谢。我刚用过。我们遇到的一个错误电子邮件地址是 something@q.com 是有效的电子邮件。我认为表达式应该从 '%_@_%_.__%' 改为 '%_@%_.__%'【参考方案2】:这是一个更详细的示例函数,我不记得我是从哪里得到的(几年前),或者我是否修改过它,否则我会包括适当的归属:
CREATE FUNCTION [dbo].[fnAppEmailCheck](@email VARCHAR(255))
--Returns true if the string is a valid email address.
RETURNS bit
as
BEGIN
DECLARE @valid bit
IF @email IS NOT NULL
SET @email = LOWER(@email)
SET @valid = 0
IF @email like '[a-z,0-9,_,-]%@[a-z,0-9,_,-]%.[a-z][a-z]%'
AND LEN(@email) = LEN(dbo.fnAppStripNonEmail(@email))
AND @email NOT like '%@%@%'
AND CHARINDEX('.@',@email) = 0
AND CHARINDEX('..',@email) = 0
AND CHARINDEX(',',@email) = 0
AND RIGHT(@email,1) between 'a' AND 'z'
SET @valid=1
RETURN @valid
END
【讨论】:
嗨cabgef,这是你给出的最佳解决方案。你能告诉我“fnAppStripNonEmail”是做什么的吗? 我需要添加条件AND CHARINDEX(' ',@email) = 0
以检查电子邮件地址中间的空格。
我知道这是一篇旧帖子,但为了其他用户的利益 - 这会引发错误:“超出最大存储过程、函数、触发器或视图嵌套级别(限制 32)”
注意:此函数错误地使包含连字符的电子邮件无效(例如,thing-thing@gmail.com)应该是有效的。
@CoreyThompson 这个函数似乎说 'thing-thing@gmail.com' 是有效的。虽然它也说 thing@thing-thing.com 也是有效的(据我了解,它不是)【参考方案3】:
很好的答案!根据这些建议,我想出了一个结合了最佳 2 个答案的简化函数。
CREATE FUNCTION [dbo].[fnIsValidEmail]
(
@email varchar(255)
)
--Returns true if the string is a valid email address.
RETURNS bit
As
BEGIN
RETURN CASE WHEN ISNULL(@email, '') <> '' AND @email LIKE '%_@%_.__%' THEN 1 ELSE 0 END
END
【讨论】:
此电子邮件将在不应该得到验证时得到验证:yourname@domain.com@domain.com【参考方案4】:分数下缺少 FnAppStripNonEmail,需要将其添加到保留值中
Create Function [dbo].[fnAppStripNonEmail](@Temp VarChar(1000))
Returns VarChar(1000)
AS
Begin
Declare @KeepValues as varchar(50)
Set @KeepValues = '%[^a-z,0-9,_,@,.,-]%'
While PatIndex(@KeepValues, @Temp) > 0
Set @Temp = Stuff(@Temp, PatIndex(@KeepValues, @Temp), 1, '')
Return @Temp
End
【讨论】:
【参考方案5】:CREATE FUNCTION fnIsValidEmail
(
@email varchar(255)
)
RETURNS bit
AS
BEGIN
DECLARE @IsValidEmail bit = 0
IF (@email not like '%[^a-z,0-9,@,.,!,#,$,%%,&,'',*,+,--,/,=,?,^,_,`,,|,,~]%' --First Carat ^ means Not these characters in the LIKE clause. The list is the valid email characters.
AND @email like '%_@_%_.[a-z,0-9][a-z]%'
AND @email NOT like '%@%@%'
AND @email NOT like '%..%'
AND @email NOT like '.%'
AND @email NOT like '%.'
AND CHARINDEX('@', @email) <= 65
)
BEGIN
SET @IsValidEmail = 1
END
RETURN @IsValidEmail
END
【讨论】:
【参考方案6】:在 SQL 2016 或 +
CREATE FUNCTION [DBO].[F_IsEmail] (
@EmailAddr varchar(360) -- Email address to check
) RETURNS BIT -- 1 if @EmailAddr is a valid email address
AS BEGIN
DECLARE @AlphabetPlus VARCHAR(255)
, @Max INT -- Length of the address
, @Pos INT -- Position in @EmailAddr
, @OK BIT -- Is @EmailAddr OK
-- Check basic conditions
IF @EmailAddr IS NULL
OR @EmailAddr NOT LIKE '[0-9a-zA-Z]%@__%.__%'
OR @EmailAddr LIKE '%@%@%'
OR @EmailAddr LIKE '%..%'
OR @EmailAddr LIKE '%.@'
OR @EmailAddr LIKE '%@.'
OR @EmailAddr LIKE '%@%.-%'
OR @EmailAddr LIKE '%@%-.%'
OR @EmailAddr LIKE '%@-%'
OR CHARINDEX(' ',LTRIM(RTRIM(@EmailAddr))) > 0
RETURN(0)
declare @AfterLastDot varchar(360);
declare @AfterArobase varchar(360);
declare @BeforeArobase varchar(360);
declare @HasDomainTooLong bit=0;
--Control des longueurs et autres incoherence
set @AfterLastDot=REVERSE(SUBSTRING(REVERSE(@EmailAddr),0,CHARINDEX('.',REVERSE(@EmailAddr))));
if len(@AfterLastDot) not between 2 and 17
RETURN(0);
set @AfterArobase=REVERSE(SUBSTRING(REVERSE(@EmailAddr),0,CHARINDEX('@',REVERSE(@EmailAddr))));
if len(@AfterArobase) not between 2 and 255
RETURN(0);
select top 1 @BeforeArobase=value from string_split(@EmailAddr, '@');
if len(@AfterArobase) not between 2 and 255
RETURN(0);
--Controle sous-domain pas plus grand que 63
select top 1 @HasDomainTooLong=1 from string_split(@AfterArobase, '.') where LEN(value)>63
if @HasDomainTooLong=1
return(0);
--Control de la partie locale en detail
SELECT @AlphabetPlus = 'abcdefghijklmnopqrstuvwxyz01234567890!#$%&‘*+-/=?^_`.|~'
, @Max = LEN(@BeforeArobase)
, @Pos = 0
, @OK = 1
WHILE @Pos < @Max AND @OK = 1 BEGIN
SET @Pos = @Pos + 1
IF @AlphabetPlus NOT LIKE '%' + SUBSTRING(@BeforeArobase, @Pos, 1) + '%'
SET @OK = 0
END
if @OK=0
RETURN(0);
--Control de la partie domaine en detail
SELECT @AlphabetPlus = 'abcdefghijklmnopqrstuvwxyz01234567890-.'
, @Max = LEN(@AfterArobase)
, @Pos = 0
, @OK = 1
WHILE @Pos < @Max AND @OK = 1 BEGIN
SET @Pos = @Pos + 1
IF @AlphabetPlus NOT LIKE '%' + SUBSTRING(@AfterArobase, @Pos, 1) + '%'
SET @OK = 0
END
if @OK=0
RETURN(0);
return(1);
END
【讨论】:
【参考方案7】:Create Function [dbo].[fnAppStripNonEmail](@Temp VarChar(1000))
Returns VarChar(1000)
AS
Begin
Declare @KeepValues as varchar(50)
Set @KeepValues = '%[^a-z,0-9,@,.,-]%'
While PatIndex(@KeepValues, @Temp) > 0
Set @Temp = Stuff(@Temp, PatIndex(@KeepValues, @Temp), 1, '')
Return @Temp
End
【讨论】:
【参考方案8】:这是选择它们的最简单方法。
使用这个查询
SELECT * FROM <TableName> WHERE [EMail] NOT LIKE '%_@__%.__%'
【讨论】:
此电子邮件将在不应该得到验证时得到验证:yourname@domain.com@domain.com【参考方案9】:托马拉克的选择
select 1
where @email not like '%[^a-z,0-9,@,.]%'
and @email like '%_@_%_.__%'
【讨论】:
以上是关于SQL 电子邮件验证(无正则表达式)的主要内容,如果未能解决你的问题,请参考以下文章