2009-02-20 18 views
10

supponendo i seguenti dati:SQL IsNumeric Restituisce True ma Rapporti SQL 'Conversione non riuscita'

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

Ho una domanda, che sta tirando i dati da questa colonna e vorrebbe per determinare se il valore è un numero, quindi restituirlo come tale nella mia domanda. Così sto facendo il seguente

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

SQL sta riportando indietro: Conversione non riuscita durante la conversione del valore varchar '11 .6' al tipo di dati int.

Perché? Ho anche cercato di forzare giocare questa:

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

ed ho ottenuto: Errore che converte il tipo di dati varchar a stare a galla.

+0

'IsNumeric()' accetta doppi/float/singoli ecc. Inoltre, non controlla gli overflow ('99999999999999999999999999999' è numerico, non converte in molti tipi di numeri). La best practice per il tipo di situazione è che non si memorizzano i dati numerici nei campi stringa nel primo posto_. –

risposta

11

è necessario sostituire virgola con un periodo:

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

SQL Server uscite separatore decimale definito con locale, ma non lo fa Unterstand tutt'altro che un periodo CAST s ai tipi numerici.

+0

Questo ha funzionato. Penso che stavo cercando qualcosa di troppo elaborato per coprire questo scenario. Grazie. –

+0

quindi '1.000' diventa 1? – dotjoe

+1

No, ho rimosso completamente la virgola. –

1

ISNUMERIC restituisce 1 quando l'espressione di input restituisce un numero intero valido, un numero in virgola mobile, un tipo di moneta o decimale;

Quindi il problema è che è un numero valido ma non un int valido.

+0

Lo vedo, ma quando provo a trasmettere valore come float ottengo lo stesso problema. –

+0

forse la virgola in 1.000 – dotjoe

1

Kyle,

Penso che questo risolva il problema. Il problema sta nel fatto che la clausola ELSE inizializza il risultato come INTEGER. Rendendo un typecast esplicito a FLOAT e aggiungendo il suggerimento di Quassnoi, sembra funzionare.

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 

saluti,
Lieven

3

Ci sono molti problemi con SQL isnumeric. Ad esempio:

select isnumeric('1e5') 

Ciò restituirà 1, ma in molte lingue, se si tenta di convertirlo in un numero, fallirà. Un approccio migliore è quello di creare la propria funzione definita dall'utente con i parametri necessari per verificare la presenza di:

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

+0

Ancora meglio: non memorizzare i campi numerici nelle colonne di stringhe in primo luogo. –

1

IsNumeric(' ') restituisce anche 1, ma poi lanciato come int fa saltare in aria. Brendan sopra dice scrivere la propria funzione. Lui ha ragione.

+1

Sul mio computer SQL 2008, 'IsNumeric ('')' restituisce '0'. – sparebytes

5

Prima converti la stringa in denaro, quindi la copri in qualsiasi altro formato numerico poiché il tipo di denaro fornisce sempre una stringa numerica vera. Non vedrai mai un errore allora.

Provate quanto segue nella vostra domanda e saprete di cosa sto parlando. Entrambi restituiranno 2345.5656. Il tipo di dati Money è arrotondato a 4 posizioni decimali, quindi il cast causa arrotondamenti a 4 cifre decimali.

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

Cast (Cast ('2.344' come denaro) come float) funziona perfettamente o cast (cast ('2.344' come denaro) come decimale (7,2)) funziona anche.

Anche il cast (CAST ('$ 2,345.56556' come denaro) int) funzionerà perfettamente arrotondandolo al numero intero più vicino.

+0

Questo è un eccellente suggerimento. – leem

0

Questa soluzione non funziona in tutti i casi (in particolare numeri con denaro e/o migliaia di separatori). Concatena una rappresentazione esponenziale alla fine del numero che è rappresentato da una stringa ... ISNUMERIC() funziona bene da lì. Esempi indicati

-- 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 

Questo, perlomeno, standardizza il formato utilizzando la funzione REPLACE().

0

Ho appena incontrato questo problema.

Puoi provare questa soluzione se non ti interessa la limitazione della lunghezza decimale.

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

NOTA:

  1. È supportato in SQL Server 2008 o superiore.
  2. denaro gamma è: -922,337,203,685,477.5808 a 922,337,203,685,477.5807 - quattro decimali.
Problemi correlati