Inicio > Sql Server 2005 - 2008 > ¿Por qué no funciona correctamente ISNUMERIC()?

¿Por qué no funciona correctamente ISNUMERIC()?


  Este es un tema muy viejo, pero, de acuerdo con un montón de posts, mucha gente todavía no entiende que ISNUMERIC() no es la función “EsTododigitos”. Hay muchos casos donde es necesario asegurar que los datos de cadena que está trabajando incluye solamente los dígitos numéricos.

La mayoría de desarrolladores utilizar el construido en función IsNumeric para realizar dicha inspección. He aquí por qué es una mala idea y qué hacer al respecto.

¿Qué es ISNUMERIC()?

“Libros en pantalla”, resume la descripción de la función IsNumeric como

“Determina si una expresión es un tipo numérico válido.”

Esto es una descripción fiable al 100% que deja mucho que desear. ¿Qué es exactamente un “tipo numérico valido”? leyendo un poco más nos encontramos con información adicional:

IsNumeric() devuelve 1 cuando la expresión de entrada se evalúa como un entero válido, número de punto flotante, el dinero o el tipo decimal, de lo contrario devuelve 0 Un valor de retorno de una garantía de que la expresión se puede convertir en uno de estos tipos numéricos.

Vamos a considerar varias conbinaciones :

SELECT ISNUMERIC (‘-10’) AS COMB1
SELECT ISNUMERIC (‘1, 000 ‘) AS COMB2
SELECT ISNUMERIC (‘d1234 0 ‘) AS COMB3
SELECT ISNUMERIC (’13e20′) AS COMB4
SELECT ISNUMERIC (‘1, 2,3,4,5 ‘) AS COMB5

Hay muchas combinaciones diferentes de letras, números y símbolos que en realidad pueden ser convertidos a los tipos de datos numéricos y ISNUMERIC() devolverá un “1” para todos ellos. No es un defecto … esa es la forma en que se supone que debe trabajar.

Lo que realmente se considera “numérico”  por la función ISNUMERIC()

Este código se muestran todos los caracteres que ISNUMERIC() toma como “numérico”

— Retorna todos los caracteres que ISNUMERIC() toma como numero
–(Utiliza los valores de 0 a 255 de la tabla de undocumented spt_Values
— instead of a loop from 0-255)
 SELECT [Ascii Code]        = STR(Number),
        [Ascii Character]   = CHAR(Number),
        [ISNUMERIC Returns] = ISNUMERIC(CHAR(Number))
   FROM Master.dbo.spt_Values
  WHERE Type = ‘P’
    AND Number BETWEEN 0 AND 255
    AND ISNUMERIC(CHAR(Number)) = 1

Código ASCII 9 es un carácter de tabulación y se incluye debido a una columna de números con frecuencia se delimitan mediante un tabulador.

Cñodigo ASCII 10 es una línea de alimentación de la fuente y se incluye porque la última columna de los números es con frecuencia termina con un avance de línea de caracteres.

Código ASCII 11 es un carácter vertical ficha y se incluye debido a que la última columna de los números es con frecuencia termina con un carácter vertical Tab.

Código ASCII 12 es una de avance de la fuente y se incluye debido a que el número de la última columna de la última fila es a veces termina con un carácter de avance.

Código ASCII 13 es un carácter de retorno de carro y se incluye debido a que la última columna de los números es con frecuencia termina con un carácter de retorno de carro.

Los códigos ASCII 36 (signo de dólar), 128 (símbolo del euro), 163 (signo Libra británica), y 164 (Yen signo) se incluyen debido a que se utilizan con frecuencia como encuestadores para identificar el tipo de número o, en este caso, la moneda escriba el número está destinado a representar.

Los códigos ASCII 43 (signo más), 44 (Coma), 45 (menos de signos), y 46 (decimal) se incluyen debido a que con frecuencia se incluye en las columnas numéricas para marcar el lugar donde en la recta numérica que aparezca el número y formato de simple.

Código ASCII 160 es un “espacio duro” y se incluye porque se utiliza con frecuencia a las columnas de la izquierda pad numérico para la columna de los números parece ser justificado a la derecha.

Código ASCII 32 es un “espacio blando” y no se incluye debido a que un solo espacio por lo general no representan una columna de números. ASCII 32 es, sin embargo, un carácter numérico válido cuando se utiliza para crear números justificado a la derecha como es código ASCII 160, pero un único código de 32 caracteres ASCII no es numérico. De hecho, una cadena de código ASCII 32 espacios no se considera ser numérico, sino una serie de espacios, incluso con un solo dígito en ella se considera ser numérico.

Código ASCII 164 es un carácter especial y se incluye porque es de uso frecuente por los contadores y algo de software para indicar un total o subtotal de algún tipo. También es utilizado por algunos para indicar que no saben lo que el enumerador.

Los códigos ASCII 48 y 59 se incluyen debido a que representan los dígitos del 0 al 9

Con suerte, he comprobado que ISNUMERIC() no es la manera de determinar si un valor o una columna de valores es que todos los dígitos. Entonces, ¿qué hacer?
Se podría escribir algo realmente complejo que recorre cada caracter para ver si es un dígito … o … podemos usar una muy simple expresion regular para hacer el trabajo sucio por nosotros.

Se crearía la función  : “EsTodosDigitos” `

— Esta función retorna 1 si el parámetro contiene sólo
— dígitos numéricos y devolverá un 0 en todos los demás casos.
— Utilícelo en una cláusula FROM, junto con CROSS APPLY cuando se utiliza contra una tabla.

CREATE  FUNCTION dbo.EsTodosDigitos
(@MiCadena VARCHAR(8000))
RETURNS TABLE AS
RETURN (
         SELECT CASE
                WHEN @MiCadena NOT LIKE ‘%[^0-9]%’
                THEN 1
                ELSE 0
                END AS EsTodosDigitos

        )

SELECT * FROM dbo.EsTodosDigitos(’10’)
SELECT * FROM dbo.EsTodosDigitos(‘1, 000 ‘)
SELECT * FROM dbo.EsTodosDigitos(‘d1234 0 ‘)
SELECT * FROM dbo.EsTodosDigitos(’13e20′)
SELECT * FROM dbo.EsTodosDigitos(‘1, 2,3,4,5 ‘)

  1. juana la loca
    17 diciembre 2010 a las 12:31 pm

    en el area se sistemas y programacion se supone que “NO” se debe suponer un coño…pajarito

    • 11 febrero 2011 a las 11:56 am

      Así es , en informática no existe el se “SUPONE”

  1. No trackbacks yet.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: