为什么ISNumeric()Transact-SQL函数将某些var-chars视为Int

时间:2018-11-29 21:11:24

标签: sql sql-server tsql

SELECT some_column 
FROM some_table 
WHERE some_column = '3.'

返回行/行

SELECT some_column 
FROM some_table 
WHERE ISNUMERIC(some_column) = 0 
  AND some_column IS NOT NULL 
  AND some_column <> ''

不返回任何非数字行/行。有一行的列值为“ 3”。

我错过了什么吗?请告知。

3 个答案:

答案 0 :(得分:2)

我不明白这个问题。 ISNUMERIC('3.')返回1。因此,第二个查询将不会返回它。而且,大概也没有其他行。

也许您确实打算:somecolumn not like '%[^0-9]%'。这样可以确保somecolumn仅包含0-9之间的数字。

在SQL Server 2012+中,您也可以使用try_convert(int, somecolumn) is not null

答案 1 :(得分:1)

ISNUMERIC()有一些缺陷。对于显然不是数字的值,它可以返回True / 1。

SELECT 
ISNUMERIC('.'), 
ISNUMERIC('$')

如果这导致您遇到问题,请尝试使用TRY_PARSE()

SELECT 
TRY_PARSE('2' AS INT)

您可以使用此过滤器过滤非空结果。

SELECT some_column 
FROM some_table 
WHERE TRY_PARSE(some_column AS INT) IS NOT NULL

答案 2 :(得分:0)

ISNUMERIC是一个遗留功能,我个人不喜欢它。它确实可以执行通常不需要的操作(“数字”是计算机科学中一个非常主观的问题。)我最近编写了此查询,以为某些同事弄清楚事情:

SELECT string = x, [isnumeric says...] = ISNUMERIC(x) 
FROM (VALUES ('1,2,3,,'),(',,,,,,,,,,'),(N'﹩'),(N'$'),(N'¢'),('12,0'),(N'52,3,1.25'),
             (N'-4,1'),(N'56.'),(N'5D105'),('1E1'),('\4'),(''),(N'\'),(N'₤'),(N'€')) x(x);

返回:

string     isnumeric says...
---------- -----------------
1,2,3,,    1
,,,,,,,,,, 1
﹩         0
$         1
¢         0
12,0       1
52,3,1.25  1
-4,1       1
56.        1
5D105      1
1E1        1
\4         1
           0
\          1
₤          1
€          1

TRY_CAST或TRY_CONVERT,或戈登所说的WHERE somecolumn not like '%[^0-9]%',可能是一个很好的选择。

出于性能方面的考虑,通过添加新的计算列来进行预聚合,持久化并为该列编制索引可能不是一个坏主意。例如。像

ALTER <your table> 
ADD isGoodNumber AS (ABS(SIGN(PATINDEX('%[^0-9]%',<your column>))-1)

对于仅包含数字的行,这将返回1,否则将返回0。然后,您可以索引isGoodNumber(选择更好的名称)以获得更好的性能。