我在使用sqlserver的ISNUMERIC函数时遇到问题,该函数为’,’返回true
我正在解析邮政编码,并尝试查看第二个字符(假定为数字)是否为0,并且在每种情况下都做不同的事情。问题是我不能只通过首先检查isNumeric来强制转换char。这是我的标量值函数的代码,该代码返回第二个char位置中的数字,如果不是数字,则返回-1。
@declare firstDigit int IF ISNUMERIC(SUBSTRING(@postal,2,1) AS int) = 1 set @firstDigit = CAST(SUBSTRING(@postal,2,1) AS int) ELSE set @firstDigit = -1 RETURN @firstdigit
由于当邮政编码不太有效时,此操作将失败。我只是想找出如何检查nvarchar @postal的第二个字符是否是0到9的数字。我已经看到了不同类型的解决方案,例如usingLIKE [0-9]或usingPATINDEX等。
LIKE [0-9]
PATINDEX
有没有更好/更简便的方法可以做到这一点?如果没有,哪种方法最快?
编辑:根据亚伦·伯特兰(Aaron Bertrand)的建议添加了代码
ON z.postal = CASE WHEN CONVERT(INT, CASE WHEN SUBSTRING(v.patientPostal,2,1) LIKE '[0-9]' THEN SUBSTRING(v.patientPostal, 2,1) END) = 0 then v.patientPostal WHEN CONVERT(INT, CASE WHEN SUBSTRING(v.patientPostal,2,1) LIKE '[0-9]' THEN SUBSTRING(v.patientPostal, 2,1) END) > 0 then LEFT(v.patientPostal,3)
如果您能够发现WHERE col LIKE '[0-9]'您想出的方法与其他方法之间的任何区别,我将感到非常惊讶。但我同意Denis的观点,将其放在函数中,以便您在所有代码中始终使用相同的检查(或者至少,如果由于大扫描等原因而避免使用UDF,请在代码中放置一个标记,便于以后进行大规模更改)。
WHERE col LIKE '[0-9]'
就是说,与使用函数内部解析的方法相比,仅使用标量UDF肯定会看到更多的性能下降。您确实应该比较UDF的性能与使用进行内联的性能CASE。例如
CASE
SELECT Postal = CONVERT(INT, CASE WHEN SUBSTRING(postal,2,1) LIKE '[0-9]' THEN SUBSTRING(postal, 2,1) END) FROM ...
NULL如果字符不是数字,则将产生此结果。
NULL
如果只处理检查局部变量,那么实际上使用什么解析方法都没有关系,最好将优化工作集中在其他地方。
编辑 添加建议的示范JOIN条款。这可能会导致较少的恒定扫描,但可读性更高(子字符串调用等要少得多):
JOIN
;WITH v AS ( SELECT /* other columns, */ patientPostal, ss = SUBSTRING(v.patientPostal,2,1), FROM [whatever table is aliased v in current query] ) SELECT /* column list */ FROM [whatever table is aliased z in current query] INNER JOIN v ON z.postal = CONVERT(INT, CASE WHEN v.ss = '0' THEN ss WHEN v.ss LIKE '[1-9]' THEN LEFT(v.patientPostal, 3) END);