SQL Server 2014:ISNUMERIC筛选无数值手机号/邮箱账户失效问题
首先得理清两个核心点:你的原始需求是严格找DayTimePhone和EmailAddress都为空的账户,还是找没有有效手机号(空或非合法格式)且没有有效邮箱的账户?这两种需求对应的SQL逻辑完全不同,我们分别来看:
情况1:你确实需要仅返回两个字段都为空的账户
如果这是你的真实需求,那你写的SQL完全绕远路了,多余的过滤条件反而帮了倒忙。直接用最直白的条件就能精准命中目标:
SELECT * FROM MyTable WHERE DayTimePhone IS NULL AND EMailAddress IS NULL
这个语句只会返回两个字段完全为空的记录,那些带数字的604.123.11...之类的记录因为DayTimePhone非空,会被直接排除,完全不需要ISNUMERIC这类函数。
情况2:你的实际需求是找“无有效手机号+无有效邮箱”的账户
从你写的SQL来看,这更可能是你的真实需求——想排除掉那些有合法手机号或邮箱的记录。那问题就出在ISNUMERIC函数的局限性,以及你的过滤条件不够精准:
为什么原SQL会返回604.123.11...?
ISNUMERIC这个函数的设计初衷不是验证“纯整数手机号”,它只会判断字符串能不能转换成SQL支持的任意数字类型(比如decimal、float)。像604.123.11...这种带多个点的字符串,无法转换成任何数字类型,所以ISNUMERIC返回0,刚好满足你写的ISNUMERIC(DayTimePhone)=0条件;同时它又不含字母,满足DayTimePhone NOT LIKE '%[A-Z]%';如果对应的EmailAddress也符合条件,自然就被返回了,但这显然不是你想要的结果。
针对性解决方案
根据你想要的过滤粒度,有两种常用的修正方式:
方案A:排除所有包含数字的DayTimePhone(只留空或完全无数字的记录)
如果你想彻底去掉任何带数字的DayTimePhone(不管格式),直接用NOT LIKE '%[0-9]%'替代ISNUMERIC:
SELECT * FROM MyTable WHERE (DayTimePhone IS NULL OR DayTimePhone NOT LIKE '%[0-9]%') AND (EMailAddress IS NULL OR EMailAddress NOT LIKE '%[A-Z]%')
这个条件会把所有包含0-9数字的DayTimePhone都排除掉,包括604.123.11...这种带点和数字的记录。
方案B:仅排除纯数字的手机号(保留空或带格式/非数字的记录)
如果你只是想排除纯数字的手机号(比如6041231111),但允许保留带分隔符的非标准格式(比如604-123-1111)或完全非数字的内容,可以用LIKE '%[^0-9]%'来判断是否包含非数字字符:
SELECT * FROM MyTable WHERE (DayTimePhone IS NULL OR DayTimePhone LIKE '%[^0-9]%') AND (EMailAddress IS NULL OR EMailAddress NOT LIKE '%[A-Z]%')
这里%[^0-9]%表示字符串中存在至少一个非数字字符,这样就能精准排除纯数字的手机号。
额外优化:精准验证邮箱格式
你原SQL里用EMailAddress NOT LIKE '%[A-Z]%'来判断无效邮箱太简陋了,如果你的SQL Server版本是2016及以上,可以用正则表达式来更精准地验证:
SELECT * FROM MyTable WHERE (DayTimePhone IS NULL OR DayTimePhone LIKE '%[^0-9]%') AND (EMailAddress IS NULL OR NOT REGEXP_LIKE(EMailAddress, '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$'))
这个正则会排除掉不符合标准邮箱格式的记录,比简单的字母判断靠谱得多。
内容的提问来源于stack exchange,提问作者user1777929




