Ten ostatni wynik powinien wynosić zero, ale sql podaje błąd

Declare @test as decimal(18,8) = 0
SET @test = @test + 0.000001375
SELECT @test --0.00000138
SET @test = @test - 0.000001375
SELECT @test --0.00000001 here it should be zero
-1
Rita Chavda 19 marzec 2020, 15:36

2 odpowiedzi

Najlepsza odpowiedź

Ma to związek z tym, w którym momencie następuje zaokrąglenie:

SET @test = @test - 0.000001375

Jeśli przejrzysz plik XML planu, zobaczysz to:

CONVERT_IMPLICIT(decimal(18,8),[@test]-(0.000001375),0)

Kluczową rzeczą, na którą należy zwrócić uwagę, jest fakt, że odejmowanie odbywa się przed konwersją z powrotem do DECIMAL(18, 8). SQL Server ma ustawia reguły precyzji i skali w zależności od operacji. Po dodaniu dwóch miejsc po przecinku skala wyniku jest definiowana jako Max(si, s2) (gdzie s1 to skala pierwszej liczby, a s2 to skala drugiej). Więc ponieważ odejmujesz DECIMAL(10, 9) od DECIMAL(18, 8), Twój wynik będzie DECIMAL(20, 9).

W momencie wykonywania tego wartość dla @test wynosi 0,00000138 (wydaje się, że już zidentyfikowałeś, że zadeklarowałeś liczbę dziesiętną (18,8), ale podałeś liczbę z 9 miejscami dziesiętnymi, że nastąpi zaokrąglenie), więc to rozszerza się do:

CONVERT_IMPLICIT(decimal(18,8),0.00000138-0.000001375,0)

Ponieważ wynik to DECIMAL(20, 9), zachowywane jest dodatkowe miejsce po przecinku. Tak więc wygląda to następująco:

CONVERT_IMPLICIT(decimal(18,8),0.000000005,0)

Ponieważ reguły zaokrąglania określają, że powinno to zaokrąglić w górę, zwracana wartość to 0,00000001, a nie 0.

4
GarethD 19 marzec 2020, 12:55

Zadeklarowałeś dziesiętny (18,8). Ta 8 w drugim parametrze mówi do sql, że twoja liczba ma 8 miejsc po przecinku. Zmień ją na 9, aby dodać ostatnią „5” w liczbie 0,000001375. W przeciwnym razie sql zaokrągli Twoją liczbę do 0,00000138

2
Felipe Fischer 19 marzec 2020, 12:43