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

时间:2011-09-22 17:57:43

标签: sql sql-server tsql sql-server-2008 isnumeric

我遇到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的数字。我见过不同类型的解决方案,例如使用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)

3 个答案:

答案 0 :(得分:7)

如果您能够发现WHERE col LIKE '[0-9]'与您提出的任何其他方法之间的任何差异,我会感到非常惊讶。但我同意Denis,将其放在一个函数中,以便在所有代码中始终如一地使用相同的检查(或者至少,如果由于大扫描等而避免使用UDF,请在代码中添加一个标记,以后可以轻松更改。

也就是说,通过使用标量UDF而不是用于在函数内部解析的方法,你肯定会看到更多的性能损失。你真的应该比较UDF的性能与使用CASE进行内联的性能。 e.g。

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);

答案 1 :(得分:3)

最好的方法是:

IF SUBSTRING(@postal,2,1) LIKE [0-9]
CAST(SUBSTRING(@postal,2,1) AS int)

答案 2 :(得分:1)

看一下IsNumeric, IsInt, IsNumber它有3种类型的检查