2009-02-20 5 views
10

Zakładając następujące dane:SQL IsNumeric Zwraca prawda ale Raporty SQL „konwersja Failed”

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

Mam kwerendy, która ciągnie dane z tej kolumny i chciałbym, aby określić, czy wartość jest liczbą, następnie zwróć go jako taki w moim zapytaniu. Więc robię następujące

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

SQL melduje z powrotem: Konwersja nie powiodła się podczas konwersji .6' wartość varchar '11 do danych typu int.

Dlaczego? Próbowałem również odrzucić to:

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

I otrzymałem: Błąd podczas konwertowania danych typu varchar na float.

+0

'IsNumeric()' zaakceptuje podwójne/zmiennoprzecinkowe/pojedyncze itd. Również nie sprawdza przepełnień ('99999999999999999999999999999' ma wartość liczbową, nie będzie konwertować na większość typów liczb). Najlepszą praktyką w tej sytuacji jest to, że nie przechowujesz danych liczbowych w polach ciągów w pierwszej kolejności. –

Odpowiedz

11

Trzeba zastąpić przecinek z okresem:

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

SQL Server wyjścia Separator dziesiętny zdefiniowany z lokalizacji, ale nie unterstand nic ale okres w CAST s do typów numerycznych.

+0

To zadziałało. Myślę, że szukałem czegoś zbyt wyszukanego, aby objąć ten scenariusz. Dzięki. –

+0

, więc "1,000" staje się 1? – dotjoe

+1

Nie, usunąłem przecinek w całości. –

1

ISNUMERIC zwraca 1, gdy wyrażenie wejściowe określa poprawną liczbę całkowitą, liczbę zmiennoprzecinkową, walutę lub typ dziesiętny;

Problem polega na tym, że jest to poprawny numer, ale nie jest to poprawna int.

+0

Widzę to, ale próbując rzucić wartość jako float, mam ten sam problem. –

+0

prawdopodobnie przecinek w 1000 – dotjoe

1

Kyle,

Myślę, że to rozwiązuje problem. Problem polega na tym, że klauzula ELSE inicjalizuje twój wynik jako INTEGER. Poprzez wyraźną typografię FLOAT i dodanie sugestii Quassnoi, wydaje się, że działa.

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 

Pozdrawiam,
Lieven

3

Istnieje wiele problemów z isNumeric SQL. Na przykład:

select isnumeric('1e5') 

To spowoduje powrót 1, ale w wielu językach, jeśli spróbujesz przekonwertować go na numer, to się nie powiedzie. Lepszym rozwiązaniem jest stworzenie własnego zdefiniowane przez użytkownika funkcji z parametrami, które trzeba sprawdzić:

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

+0

Lepiej: nie przechowuj pól liczb w kolumnach ciągów w pierwszej kolejności. –

1

IsNumeric(' ') również zwraca 1, ale wtedy CAST jako int wysadza. Brendan powyżej mówi napisać własną funkcję. On ma rację.

+1

Na moim komputerze z SQL 2008, 'IsNumeric ('')' zwraca '0'. – sparebytes

5

Najpierw skonwertuj ciąg na pieniądze, a następnie zamień go na dowolny inny format liczbowy, ponieważ typ ceny zawsze podaje prawdziwy łańcuch liczbowy. Nigdy nie zobaczysz wtedy błędu.

Spróbuj wykonać następujące czynności w zapytaniu, a dowiesz się, o czym mówię. Obie zwrócą 2345.5656. Typ danych Pieniądze jest zaokrąglany do 4 miejsc dziesiętnych, a zatem rzutowanie powoduje zaokrąglenie do 4 miejsc dziesiętnych.

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

Obsada (cast ('2344' jak pieniądze) jako float) będzie działać idealnie lub wylewane (obsady ('2344' jako pieniędzy) jako przecinku (7,2)) będzie również działać.

Nawet rzut (CAST ("234,556556" jako pieniądze) jako int) działa idealnie zaokrąglając go do najbliższej liczby całkowitej.

+0

To jest doskonała propozycja. – leem

0

To rozwiązanie nie działa we wszystkich przypadkach (w szczególności numery z pieniędzmi i/lub tysiącami separatorów). Łączenie reprezentacji wykładniczej na końcu liczby, która jest reprezentowana przez ciąg ... ISNUMERIC() działa dobrze stamtąd. Poniższe przykłady:

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

To co najmniej standaryzuje format używania funkcji REPLACE().

0

Właśnie spotkałem się z tym problemem.

Możesz wypróbować to rozwiązanie, jeśli nie masz nic przeciwko ograniczeniu długości dziesiętnej.

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

UWAGA:

  1. Jest obsługiwane w SQL Server 2008 lub powyżej.
  2. Pieniądze zakres to: -922,337,203,685,477.5808 do 922,337,203,685,477.5807 - cztery miejsca po przecinku.