La ISNUMERIC
función tiene un comportamiento inesperado. La documentación de MSDN dice:
ISNUMERIC
devuelve 1 cuando la expresión de entrada se evalúa como un tipo de datos numéricos válido; de lo contrario, devuelve 0. Los tipos de datos numéricos válidos incluyen los siguientes: int, bigint, smallint, tinyint, decimal, numérico, money, smallmoney, float, real .
Y también tiene una nota al pie:
ISNUMERIC
devuelve 1 para algunos caracteres que no son números, como más (+), menos (-) y símbolos de moneda válidos, como el signo de dólar ($). Para obtener una lista completa de los símbolos de moneda, vea money and smallmoney (Transact-SQL) .
De acuerdo, entonces +
, -
y los símbolos de moneda listados se considerarán numéricos. Hasta aquí todo bien.
Ahora para la parte extraña. En primer lugar, algunos de los símbolos de moneda del artículo vinculado no son numéricos, incluidos:
- Signo de Euro-Moneda, hex 20A0:
₠
- Signo de Naira, hex 20A6:
₦
- Signo de Rial, hex FDFC:
﷼
Esto es extraño, y parece que no puedo entender por qué. ¿Es esta versión o entorno dependiente?
Sin embargo, las cosas se ponen más raras. Aquí hay algunos otros que no puedo explicar:
/
no es numérico, pero\
es (¿ eh? )REPLICATE(N'9', 308)
es numérico, peroREPLICATE(N'9', 309)
no es
La primera y más básica pregunta es: ¿qué explica los casos anteriores? Más importante aún: ¿cuál es la lógica detrásISNUMERIC
, para poder explicar / predecir todos los casos yo mismo?
Aquí hay una buena forma de reproducir cosas:
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;
Cuando ejecuto esto en mi cuadro local de SQL Server 2012 obtengo los siguientes resultados:
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
fuente
0
de cinco de los valores que realmente funcionanmoney
. Los otros parecen precisos. SQL FIDDLENCHAR(0) - NCHAR(65535)
veo 112 discrepancias. Incluyendo personajes como los₁,₂,₃,4,5,6,7,8,9
que parecen numéricos pero no se lanzan con éxito a nada para mí. FiddleRespuestas:
Los comportamientos detallados de
ISNUMERIC
no están documentados y probablemente nadie los conozca sin acceso al código fuente. Dicho esto, puede ser que la interpretación dependa de la categorización Unicode (numérica o no). Del mismo modo, los casos extraños que menciona pueden ser errores que se conservan para la compatibilidad con versiones anteriores. Sí, sé que suena loco, pero sucede.Como está utilizando SQL Server 2012, no hay necesidad de usarlo
ISNUMERIC
. UtiliceTRY_CONVERT
o el sinónimo en suTRY_CAST
lugar para verificar si una cadena es convertible a un tipo dado. Cuando proporcionan una funcionalidad adecuada, estos son preferibles aTRY_PARSE
, porque este último implica un procesamiento más costoso a través de la integración CLR.fuente
La barra invertida ASCII (punto de código 5C) comparte el mismo punto de código que el signo yen (¥) en la codificación Shift-JIS utilizada por la versión japonesa de Windows, y el signo ganado (₩) en EUC-KR coreano. Por lo tanto, es muy probable que solo sea una continuación del tema del signo de moneda.
fuente
money
que se dirige también.C:¥Program Files¥
en explorer.exe