该ISNUMERIC
函数具有某些意外行为。MSDN文档说:
ISNUMERIC
当输入表达式的计算结果为有效的数值数据类型时,返回1;否则返回0。有效的数字数据类型包括以下类型:int,bigint,smallint,tinyint,十进制,数字,money,smallmoney,float,real。
它也有一个脚注:
ISNUMERIC
对于非数字字符(例如加号(+),减号(-))和有效的货币符号(例如美元符号($)),返回1。有关货币符号的完整列表,请参见money和smallmoney(Transact-SQL)。
好的,因此+
,-
和列出的货币符号应被视为数字。到目前为止,一切都很好。
现在是奇怪的部分。首先,链接文章中的某些货币符号不是数字,包括:
- 欧元货币符号,十六进制20A0:
₠
- 奈拉符号,十六进制20A6:
₦
- 里亚尔符号,十六进制FDFC:
﷼
这很奇怪,我似乎找不到原因?此版本或环境相关吗?
但是,事情变得奇怪了。这里有一些我无法解释的内容:
/
不是数字,而是\
(呵呵!)REPLICATE(N'9', 308)
是数字,但REPLICATE(N'9', 309)
不是
第一个也是最基本的问题是:什么能解释上述情况?但更重要的是:背后的逻辑是什么ISNUMERIC
,以便我自己解释/预测所有情况?
这是重现事物的好方法:
DECLARE @tbl TABLE(txt NVARCHAR(1000));
INSERT INTO @tbl (txt)
VALUES (N''), (N' '), (N'€'), (N'$'), (N'$$'),
(NCHAR(8356)), (NCHAR(8352)), (NCHAR(8358)), (NCHAR(65020)),
(N'+'), (N'-'), (N'/'), (N'\'), (N'_'), (N'e'), (N'1e'), (N'e1'), (N'1e1'),
(N'1'), (N'-1'), (N'+1'), (N'1+1'), (N'⒈'), (N'🄂'), (N'¹'), (N'①'), (N'½'),
(N'🎅'), (REPLICATE(N'9', 307)), (REPLICATE(N'9', 308)), (REPLICATE(N'9', 309)),
(REPLICATE(N'9', 310));
SELECT UNICODE(LEFT(txt, 1)) AS FirstCharAsInt,
LEN(txt) AS TxtLength,
txt AS Txt,
ISNUMERIC(txt) AS [ISNUMERIC]
FROM @tbl;
当我在本地Sql Server 2012框上运行此命令时,得到以下结果:
FirstCharAsInt TxtLength Txt ISNUMERIC
--------------- ---------- --------- ----------
NULL 0 0
32 0 0
8364 1 € 1
36 1 $ 1
36 2 $$ 0
8356 1 ₤ 1
8352 1 ₠ 0 --??
8358 1 ₦ 0 --??
65020 1 ﷼ 0 --??
43 1 + 1
45 1 - 1
47 1 / 0
92 1 \ 1 --??
95 1 _ 0
101 1 e 0
49 2 1e 0
101 2 e1 0
49 3 1e1 1
49 1 1 1
45 2 -1 1
43 2 +1 1
49 3 1+1 0
9352 1 ⒈ 0
55356 2 🄂 0
185 1 ¹ 0
9312 1 ① 0
189 1 ½ 0
55356 2 🎅 0
57 307 /*...*/ 1
57 308 /*...*/ 1 --??
57 309 /*...*/ 0 --??
57 310 /*...*/ 0
0
了实际上精确到的五个值money
。其他似乎准确。SQL FIDDLE