ISNUMERIC
Функция имеет некоторое неожиданное поведение. Документация MSDN гласит:
ISNUMERIC
возвращает 1, когда входное выражение оценивается как допустимый числовой тип данных; в противном случае возвращается 0. Допустимые числовые типы данных включают следующие: int, bigint, smallint, tinyint, десятичное, числовое, money, smallmoney, float, real .
И это также имеет сноску:
ISNUMERIC
возвращает 1 для некоторых символов, которые не являются числами, такими как плюс (+), минус (-), и допустимыми символами валюты, такими как знак доллара ($). Для полного списка символов валюты см. Money и smallmoney (Transact-SQL) .
Итак +
, -
и перечисленные символы валюты, как ожидается, будут считаться числовыми. Все идет нормально.
Теперь о странной части. Прежде всего, некоторые символы валюты из связанной статьи не являются числовыми, в том числе:
- Знак евро-валюты, гексагон 20A0:
₠
- Знак наира, шестнадцатеричный 20А6:
₦
- Знак Rial, шестнадцатеричный 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 FIDDLENCHAR(0) - NCHAR(65535)
112 я вижу несоответствия. Включая такие символы,₁,₂,₃,4,5,6,7,8,9
которые выглядят числовыми, но не приводят меня ни к чему успешному. СкрипкаОтветы:
Подробное поведение
ISNUMERIC
не документировано и, вероятно, не полностью известно никому без доступа к исходному коду. Тем не менее, возможно, что интерпретация зависит от классификации Unicode (числовой или нет). Точно так же странные случаи, о которых вы упоминаете, могут быть ошибками, которые сохраняются для обратной совместимости. Да, я знаю, это звучит безумно, но это случается.Поскольку вы используете SQL Server 2012, нет необходимости использовать
ISNUMERIC
. Вместо этого используйтеTRY_CONVERT
или синоним,TRY_CAST
чтобы проверить, может ли строка быть преобразована в данный тип. Там, где они обеспечивают адекватную функциональность, это предпочтительнееTRY_PARSE
, поскольку последняя включает в себя более дорогую обработку посредством интеграции CLR.источник
Обратная косая черта ASCII (кодовая точка 5C) имеет ту же кодовую точку, что и знак иены (¥) в кодировке Shift-JIS, используемой в японской версии Windows, и знак выигрыша (₩) в корейском EUC-KR. Следовательно, это очень вероятно, просто продолжение темы знак валюты.
источник
money
то, что он бросает также.C:¥Program Files¥
в explorer.exe