我遇到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)
答案 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种类型的检查