La ISNUMERIC
fonction a un comportement inattendu. La documentation MSDN indique:
ISNUMERIC
renvoie 1 lorsque l'expression d'entrée est évaluée en un type de données numérique valide; sinon, il renvoie 0. Les types de données numériques valides sont les suivants: int, bigint, smallint, tinyint, decimal, numeric, money, smallmoney, float, real .
Et il a également une note de bas de page:
ISNUMERIC
renvoie 1 pour certains caractères qui ne sont pas des nombres, tels que plus (+), moins (-) et des symboles monétaires valides tels que le signe dollar ($). Pour une liste complète des symboles monétaires, consultez money and smallmoney (Transact-SQL) .
D'accord, donc +
, -
et les symboles monétaires répertoriés devraient être considérés comme numériques. Jusqu'ici tout va bien.
Maintenant pour la partie étrange. Tout d'abord, certains des symboles monétaires de l'article lié ne sont pas numériques, notamment:
- Signe euro-monnaie, hex 20A0:
₠
- Signe Naira, hex 20A6:
₦
- Signe Rial, hex FDFC:
﷼
C'est bizarre, et je n'arrive pas à découvrir pourquoi? Cette version ou l'environnement dépend-il?
Cependant, les choses deviennent plus étranges. Voici quelques autres que je ne peux pas expliquer:
/
n'est pas numérique, mais l'\
est ( Huh?! )REPLICATE(N'9', 308)
est numérique, maisREPLICATE(N'9', 309)
n'est pas
La première question, la plus fondamentale, est: qu'est-ce qui explique les cas ci-dessus? Mais plus important encore: quelle est la logique derrièreISNUMERIC
, afin que je puisse expliquer / prédire tous les cas moi-même?
Voici un bon moyen de reproduire des choses:
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;
Lorsque j'exécute cela sur ma boîte Sql Server 2012 locale, j'obtiens les résultats suivants:
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
NCHAR(0) - NCHAR(65535)
je vois 112 écarts. Y compris des caractères tels que ceux ₁,₂,₃,4,5,6,7,8,9
qui semblent numériques mais qui ne réussissent pas à quelque chose pour moi. Violon
0
cinq des valeurs qui conviennent réellementmoney
. Les autres semblent exacts. SQL FIDDLE