一尘不染

检查字符是否为数字的最快方法?

sql

我在使用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等。

有没有更好/更简便的方法可以做到这一点?如果没有,哪种方法最快?

编辑:根据亚伦·伯特兰(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)

阅读 134

收藏
2021-03-17

共1个答案

一尘不染

如果您能够发现WHERE col LIKE '[0-9]'您想出的方法与其他方法之间的任何区别,我将感到非常惊讶。但我同意Denis的观点,将其放在函数中,以便您在所有代码中始终使用相同的检查(或者至少,如果由于大扫描等原因而避免使用UDF,请在代码中放置一个标记,便于以后进行大规模更改)。

就是说,与使用函数内部解析的方法相比,仅使用标量UDF肯定会看到更多的性能下降。您确实应该比较UDF的性能与使用进行内联的性能CASE。例如

SELECT Postal = CONVERT(INT, CASE WHEN SUBSTRING(postal,2,1) LIKE '[0-9]' 
       THEN SUBSTRING(postal, 2,1) END)
FROM ...

NULL如果字符不是数字,则将产生此结果。

如果只处理检查局部变量,那么实际上使用什么解析方法都没有关系,最好将优化工作集中在其他地方。

编辑 添加建议的示范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);
2021-03-17