SQL Server 2005 numeriese presisie verlies
-
02-07-2019 - |
Vra
Die fout opsporing sommige finansies-verwante SQL-kode het 'n vreemde kwessie met numeriese (24,8) wiskunde presisie.
Die uitvoer van die volgende navraag op jou MSSQL jy sou kry A + B * C uitdrukking gevolg te wees 0,123457
Kies 'n, B, C, A + B * C VAN ( SELECT CAST (0.12345678 AS NUMERIC (24,8)) AS A, CAST (0 AS NUMERIC (24,8)) AS B, CAST (500 AS NUMERIC (24,8)) AS C ) T
So het ons verloor 2 beduidende simbole. Probeer om hierdie vaste kry op verskillende maniere Ek het dit omskakeling van die intermediêre vermenigvuldiging gevolg (wat is Zero!) Om numeriese (24,8) sou werk boete.
En laastens 'n het 'n oplossing. Maar nog steeds ek hace n vraag - hoekom MSSQL optree op hierdie manier en watter tipe doelskoppe eintlik plaasgevind in my monster
?Oplossing
Net soos byvoeging van die tipe float is verkeerd, vermenigvuldiging van die desimale tipes kan onakkurate wees (of onnoukeurigheid veroorsaak) as jy die akkuraatheid oorskry. Sien Data Type Gesprek en desimale en numeriese .
Aangesien jy NUMERIC(24,8)
en NUMERIC(24,8)
, en SQL Server vermenigvuldig sal net seker die tipe nie die inhoud, is dit waarskynlik sal probeer om die potensiaal 16 nie-desimale syfers (24-8) te red wanneer dit nie al 48 syfers van kan red presisie (maksimum is 38). Kombineer twee van hulle, kry jy 32 nie-desimale syfers, wat jy verlaat met net 6 desimale syfers (38-32).
So het die oorspronklike navraag
SELECT A, B, C, A + B * C
FROM ( SELECT CAST(0.12345678 AS NUMERIC(24,8)) AS A,
CAST(0 AS NUMERIC(24,8)) AS B,
CAST(500 AS NUMERIC(24,8)) AS C ) T
verminder na
SELECT A, B, C, A + D
FROM ( SELECT CAST(0.12345678 AS NUMERIC(24,8)) AS A,
CAST(0 AS NUMERIC(24,8)) AS B,
CAST(500 AS NUMERIC(24,8)) AS C,
CAST(0 AS NUMERIC(38,6)) AS D ) T
Weereens, tussen NUMERIC(24,8)
en NUMERIC(38,6)
, SQL Server sal probeer om die potensiaal 32 syfers van nie-desimale red, so A + D
verminder na
SELECT CAST(0.12345678 AS NUMERIC(38,6))
wat gee jou 0.123457
na afronding.
Ander wenke
Na aanleiding van die logika uitgewys deur eed3si9n en wat jy sê in jou vraag blyk dit dat die beste benadering wanneer jy wiskunde bedrywighede is om hulle te onttrek in 'n funksie en addisioneel tot presisie spesifiseer na elke operasie,
Dit hierdie geval die funksie kon so iets lyk:
create function dbo.myMath(@a as numeric(24,8), @b as numeric(24,8), @c as numeric(24,8))
returns numeric(24,8)
as
begin
declare @d as numeric(24,8)
set @d = @b* @c
return @a + @d
end
Ten spyte van wat dit sê op Precision, Skaal en lengte (Transact-SQL) . Ek glo dit is ook 'n minimum skaal (aantal desimale plekke) van 6 tot die gevolglike NUMERIC tipe vir vermenigvuldiging dieselfde as dit nie vir verdeling ens.