2009-02-20 24 views
10

Suponiendo los siguientes datos:SQL IsNumeric Devuelve True pero los informes de SQL 'Error de conversión'

Column1 (data type: varchar(50)) 
-------- 
11.6 
-1 
1,000 
10"  
Non-Numeric String 

Tengo una consulta, que está tirando de datos de esta columna y le gustaría para determinar si el valor es un número, luego devolverlo como tal en mi consulta. Así que estoy haciendo lo siguiente

SELECT CASE WHEN IsNumeric(Replace(Column1,'"','')) = 1 Then Replace(Column1,'"','') Else 0 End As NumericValue 

SQL es informar: Error de conversión al convertir el valor varchar 0,6' '11 a tipo de datos int.

¿Por qué? También intenté forzar a lanzar esto:

SELECT CASE WHEN IsNumeric(Replace(Column1,'"','')) = 1 Then cast(Replace(Column1,'"','') as float) Else 0 End As NumericValue 

Y obtuve: Error al convertir el tipo de datos varchar a float.

+0

'IsNumeric()' aceptará dobles/flotantes/sencillos, etc. Además, no comprueba los desbordamientos ('99999999999999999999999999999' es numérico, no se convertirá a la mayoría de los tipos de números). La mejor práctica para el tipo de situación es que, en primer lugar, no almacena datos numéricos en campos de cadenas. –

Respuesta

11

Es necesario sustituir la coma con un período de:

CAST(REPLACE(column, ',', '.') AS FLOAT) 

SQL Server salidas de notación decimal definido con la configuración regional, pero no hace nada Unterstand sino un período en el CAST s a tipos numéricos.

+0

Esto funcionó. Creo que estaba buscando algo demasiado elaborado para cubrir este escenario. Gracias. –

+0

entonces '1,000' se convierte en 1? – dotjoe

+1

No, eliminé la coma por completo. –

1

ISNUMERIC devuelve 1 cuando la expresión de entrada evalúa un entero válido, número de punto flotante, dinero o tipo decimal;

El problema es que es un número válido pero no es un int válido.

+0

Veo eso, pero cuando intento arrojar valor como float, tengo el mismo problema. –

+0

posiblemente la coma en 1,000 – dotjoe

1

Kyle,

Creo que esto resuelve el problema. El problema radica en el hecho de que la cláusula ELSE inicializa el resultado para que sea INTEGER. Al hacer un encasillado explícito para FLOTAR y agregar la sugerencia de Quassnoi, parece funcionar.

DECLARE @MyTable TABLE (Column1 VARCHAR(50)) 
INSERT INTO @MyTable VALUES('11.6') 
INSERT INTO @MyTable VALUES('-1') 
INSERT INTO @MyTable VALUES('1,000') 
INSERT INTO @MyTable VALUES('10" ') 
INSERT INTO @MyTable VALUES('Non-Numeric String') 

SELECT CASE WHEN ISNUMERIC(REPLACE(Column1,'"','')) = 1 THEN REPLACE(REPLACE(Column1,'"',''), ',', '.') ELSE CAST(0 AS FLOAT) END 
FROM @MyTable 

Saludos,
Lieven

3

Hay muchos problemas con SQL isnumeric. Por ejemplo:

select isnumeric('1e5') 

Esto devolverá 1 pero en muchos idiomas si intenta convertirlo a un número, fallará. Un mejor enfoque es crear su propia función definida por el usuario con los parámetros que necesita para comprobar:

http://www.tek-tips.com/faqs.cfm?fid=6423

+0

Mejor aún: no almacene campos numéricos en columnas de cadenas en primer lugar. –

1

IsNumeric(' ') también devuelve 1, pero luego echado como int explota. Brendan arriba dice que escribe tu propia función. Él está correcto.

+1

En mi máquina SQL 2008, 'IsNumeric ('')' devuelve '0'. – sparebytes

5

Primero convierta el hilo en dinero, luego encájelo en cualquier otro formato numérico ya que el tipo de dinero da siempre una cadena numérica verdadera. Nunca verás un error entonces.

Intente lo siguiente en su consulta y sabrá de lo que estoy hablando. Ambos devolverán 2345.5656. El tipo de datos Money se redondea a 4 lugares decimales y, por lo tanto, la conversión provoca el redondeo a 4 decimales.

SELECT CAST('2,345.56556' as money), CAST('$2,345.56556' as money) 

moldeada (molde ('2344' como dinero) como float) funcione a la perfección o molde (molde ('2344' como dinero) como un decimal (7,2)) también funcionará.

Incluso el elenco (CAST ('$ 2,345.56556' como dinero) como int) funcionará perfectamente redondeándolo al número entero más cercano.

+0

Esta es una excelente sugerencia. – leem

0

Esta solución no funciona en todos los casos (específicamente números con dinero y/o separadores de miles). Concatenar una representación de exponente al final del número que está representado por una cadena ... ISNUMERIC() funciona bien desde allí. Ejemplos a continuación:

-- CURRENT ISNUMERIC RESULTS 
SELECT ISNUMERIC('11.6'); --1 
SELECT ISNUMERIC ('-1'); --1 
SELECT ISNUMERIC('1,000'); --1 
SELECT ISNUMERIC('10"'); --0 
SELECT ISNUMERIC('$10'); --1 

-- NEW ISNUMERIC RESULTS 
SELECT ISNUMERIC('11.6'+'e+00'); --1 
SELECT ISNUMERIC ('-1'+'e+00'); --1 
SELECT ISNUMERIC('1,000'+'e+00'); --0 
SELECT ISNUMERIC('10"'+'e+00'); --0 
SELECT ISNUMERIC('$10'+'e+00'); --0 

Esto, al menos, estandariza el formato para usar la función REPLACE().

0

Acabo de resolver este problema.

Puede probar esta solución si no le importa la limitación de la longitud decimal.

CONVERT(numeric, CONVERT(money, '.')) 

NOTA:

  1. Es apoyado en SQL Server 2008 o superior.
  2. dinero gama es: -922,337,203,685,477.5808 a 922,337,203,685,477.5807 - cuatro decimales.
Cuestiones relacionadas