3

我遇到了 sqlserver 的 ISNUMERIC 函数的问题,它为 ',' 返回 true

我正在解析邮政编码并尝试查看第二个字符(应该是数字)是否为 0,并在每种情况下执行不同的操作。问题是我不能通过首先检查 isNumeric 来转换字符。这是我的标量值函数的代码,用于返回第二个字符位置中的数字,如果不是数字,则返回 -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 之间的数字。我见过不同类型的解决方案,例如使用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)
4

3 回答 3

9

如果您能够发现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);
于 2011-09-22T18:03:01.387 回答
3

最好的方法是:

IF SUBSTRING(@postal,2,1) LIKE [0-9]
CAST(SUBSTRING(@postal,2,1) AS int)
于 2011-09-22T18:03:23.253 回答
1

看看IsNumeric、IsInt、IsNumber它检查了这 3 种类型

于 2011-09-22T18:00:24.273 回答