Frage

Debuggen einiger finanzbezogenen SQL-Code ein seltsames Problem mit numeric (24,8) Mathematik Präzision gefunden.

Ausführen der folgenden Abfrage auf Ihrem MSSQL Sie A + B * C Ausdruck Ergebnis erhalten würde 0,123457

sein

A SELECT,        B,        C,        A + B * C VON ( SELECT CAST (0.12345678 als numerische (24,8)) als A,        CAST (0 AS ZIFFERN (24,8)) als B,        CAST (500 AS ZIFFERN (24,8)) als C ) T

So haben wir zwei bedeutende Symbole verloren. Der Versuch, dies erhalten auf verschiedene Weise festgelegt bekam ich, dass die Umwandlung des Zwischenmultiplikationsergebnisses (die Null!) In numerischen (24,8) würde gut funktionieren.

Und schließlich eine Lösung. Aber noch hace ich eine Frage - warum MSSQL auf diese Weise verhält und welche Typkonvertierungen in meiner Probe tatsächlich aufgetreten

?
War es hilfreich?

Lösung

Wie Zugabe des Schwimmers Typ ist ungenau, Multiplikation der Dezimaltypen können ungenau sein (oder Ungenauigkeit verursachen), wenn Sie die Genauigkeit nicht überschreiten. Siehe Datentypkonvertierung und decimal und numeric .

Da Sie NUMERIC(24,8) und NUMERIC(24,8) multipliziert und SQL Server wird nur die Art überprüfen nicht der Inhalt, es wird wahrscheinlich versuchen, die möglichen 16 nicht-Dezimalstellen zu speichern (24-8), wenn sie nicht alle 48 Ziffern speichern kann Genauigkeit (max 38). Kombinieren Sie zwei von ihnen, erhalten Sie 32 Nicht-Dezimalstellen, die Sie mit nur 6 Dezimalstellen Blätter (38-32).

Damit wird die ursprüngliche Abfrage

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

reduziert auf

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

Auch zwischen NUMERIC(24,8) und NUMERIC(38,6), wird SQL Server versuchen, die möglichen 32 Stellen von Nicht-Dezimalstellen zu speichern, so A + D zu reduzieren

SELECT CAST(0.12345678 AS NUMERIC(38,6))

das gibt Sie 0.123457 nach dem Runden.

Andere Tipps

der Logik folgend wies darauf hin, von eed3si9n und was Sie gesagt haben in Ihrer Frage scheint es, dass der beste Ansatz, wenn Mathematik Operationen ist, um sie in eine Funktion zu extrahieren und zusätzlich angeben Präzision nach jeder Operation,

tun

Es diesem Fall ist die Funktion etwas aussehen könnte:

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

Trotz allem, was er sagt, auf Precision, Mensur und Länge (Transact-SQL) . Ich glaube, es ist auch ein Minimum ‚Skala‘ (Anzahl der Dezimalstellen) von 6 zur resultierenden NUMERIC-Typ für die Multiplikation der Anwendung das gleiche wie es funktioniert für die Division etc.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top