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

?
Was dit nuttig?

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.

Gelisensieer onder: CC-BY-SA met toeskrywing
Nie verbonde aan StackOverflow
scroll top