2012-10-31 6 views
6

Poniżej znajduje się podzbiór rodzaju struktury tabeli i danych, z którymi pracuję.Błąd przepełnienia arytmetycznego konwertujący varchar na typ danych liczbowych. '10' <= 9.00

CREATE TABLE #Test 
(
    Val varchar(5) 
    ,Type varchar(5) 
) 

INSERT #Test VALUES ('Yes','Text') 
INSERT #Test VALUES ('10','Int') 
INSERT #Test VALUES ('10.00','Float') 
INSERT #Test VALUES ('9.00','Float') 
INSERT #Test VALUES ('9','Int') 

Chcę napisać kwerendę, która będzie dać mi znać, jeśli kolumna „Val” jest < = 9.00 (musi być typu danych numerycznych). Zrobiłem to, wykonując następujące czynności:

SELECT * 
FROM 
    (
     SELECT Val 
     FROM #Test 
     WHERE Type = 'Int' 
    ) IntsOnly 
WHERE IntsOnly.Val <= 9.00 

Daje mi to błąd błędu arytmetycznego. Jeśli jednak wykluczyć wiersz danych o wartości "10":

SELECT * 
FROM 
    (
     SELECT Val 
     FROM #Test 
     WHERE Type = 'Int' 
     AND Val <> '10' 
    ) IntsOnly 
WHERE IntsOnly.Val <= 9.00 

Działa bez żadnego problemu. Moje pytanie nie polega na rozwiązaniu tego problemu, ponieważ wiem, że mogę po prostu przekształcić dane w wymagany przeze mnie format.

Moje pytanie brzmi, dlaczego wartość "10" w kolumnie "Val" zwraca błąd. Z pewnością logika powinna po prostu zwrócić "False" i po prostu wykluczyć wiersze, ponieważ "10" (które, jak zakładam, jest niejawnie skonwertowane) jest większe niż 9.00.

Dzięki.

+1

błąd przepełnienia arytmetyka, jesteś pewien? Nie [błąd konwersji] (http://stackoverflow.com/q/9136722/11683)? – GSerg

+0

Spróbuj być *** *** w konwersji. Co daje 'CAST (val AS DECIMAL (9,2)) <= CAST (9.00 AS DECIMAL (9,2))? – MatBailie

+0

GSerg - Tak, przepełnienie arytmetyczne konwertujące varchar na numeryczne. Dems - To działa! Chciałbym jednak zrozumieć, dlaczego niejawna konwersja nie działa? Myślałem, że to może zrobić to nawrócenie i nie powinno powodować problemu? – JBond

Odpowiedz

9

ten generuje przepełnienie ponieważ próbuje pośrednio odlew kolumnę Val do numerycznej (3,2), co oczywiście będzie przechodzić od wartości dwóch cyfr, jak 10.

jest za pomocą przycisków numerycznych (3 , 2) jako typ i rozmiar celu, ponieważ jest to najmniejsza liczba, którą wydaje się zmieścić 9.00.

Rozwiązanie, oczywiście, jest użycie explict Casting zamiast robić to w sposób dorozumiany

+0

Zauważyłem też, że możemy powiedzieć, że masz "Decimal (5,3)", a liczba, którą masz, to "12.321", która zostanie zaakceptowana. Ale jeśli twój numer to '123.321' <- to jest" 6 cyfr w sumie ", więc nie zaakceptuj go. Dziesiętny powinien być wtedy "Dziesiętny (6,3)". To jest właśnie coś, co przetestowałem i potwierdziłem sobie 'SQL 2014' – Pierre

+2

@Pierre Tak, to dosłownie definicja specyfikacji typu" DECIMAL ". – RBarryYoung

4

Z BOL:

W Transact-SQL stałe z przecinkiem automatycznie przekształca się w numerycznej wartości danych, przy użyciu minimalnej koniecznej dokładności i skalę. Na przykład, stały 12.345 przekształca się w wartości liczbowej z dokładnością do 5, a skalę 3.

To znaczy, że będzie miał stałą 9.00 dokładnością do 1, a w skali od 0 dokładnością 3 i skali 2, więc nie może przechowywać wartości 10, która wymaga minimalnej precyzji 2 + scale.

Musisz zawinąć IntsOnly.Val za pomocą CAST lub CONVERT, aby określić poprawną precyzję i skalę.

+0

Jestem pewien, że chciałeś napisać skalę 2? –

+0

Zależy od tego, jak sprytny jest silnik SQL; może przekonwertować na "numeryczne (3, 2)", ponieważ po kropce dziesiętnej są dwie cyfry, lub może zostać zamienione na "numeryczne (1, 0)", ponieważ cyfry po przecinku dziesiętnym są równe "0" . –

+0

Sprawdza wszystkie zera po prawej stronie przecinka dziesiętnego, ale ignoruje wszystkie zera wiodące po lewej stronie. Tak więc '00000.0000' daje' numeric (4,4) ' –

Powiązane problemy