Frage

Ich bin mit einem decimal-Spalte, um Geld zu speichern die Werte in einer Datenbank, und heute wurde ich gefragt, was die Genauigkeit und die Dezimalstellen zu verwenden.

Da angeblich bei char-Spalten eine Feste Breite effizienter sind, ich dachte das gleiche könnte wahr sein, für decimal-Spalten.Ist es?

Und was die Genauigkeit und die Dezimalstellen sollte ich verwenden?Ich dachte, Präzision 24/8.Ist das übertrieben, nicht genug oder ok?


Dies ist, was ich beschlossen habe zu tun:

  • Speichern Sie die conversion-raten (wenn zutreffend) in der transaktionstabelle sich, wie ein Schwimmer
  • Lagern Sie die Währung in der Tabelle
  • Der Transaktionsbetrag wird ein DECIMAL(19,4)
  • Alle Berechnungen mit einem conversion rate wird behandelt werden in meiner Anwendung, so dass ich unter Kontrolle zu halten Rundung Probleme

Ich glaube nicht, dass ein Schwimmer, der für die conversion-rate ist ein Problem, da es meistens für Referenz, und ich werde Gießen Sie es in eine Dezimalzahl sowieso.

Ich danke Ihnen allen für Ihre wertvollen Beiträge.

War es hilfreich?

Lösung

Wenn Sie suchen für eine one-size-fits-all, ich würde vorschlagen, DECIMAL(19, 4) ist eine beliebte Wahl (eine schnelle Google bestätigt dies).Ich denke, dieser stammt aus der alten VBA/Access/Jet-Datentyp "Währung", die als erste Feste Punkt decimal-Typ ist in der Sprache; Decimal nur kam 'version 1.0' style (d.h.nicht vollständig umgesetzt) in VB6/VBA6/Jet 4.0.

Die Faustregel für Lagerung der Feste Punkt-dezimal-Werten zu speichern, mindestens eine weitere Dezimalstelle, als Sie tatsächlich benötigen, um zu ermöglichen, für die Rundung.Einer der Gründe für die Zuordnung der alten Currency geben Sie in das front-end auf DECIMAL(19, 4) geben Sie in die zurück Ende war, dass Currency ausgestellt Banker Rundung von der Natur, in der Erwägung, dass DECIMAL(p, s) gerundet durch abschneiden.

Eine zusätzliche Dezimalstelle bei Lagerung DECIMAL ermöglicht eine benutzerdefinierte Rundung Algorithmus implementiert werden, anstatt die Verkäufer die Standard - (und Banker Rundung ist erschreckend, um es gelinde zu sagen, für einen designer, dass alle Werte endet in 5 Runde Weg von null).

Ja, DECIMAL(24, 8) klingt wie overkill zu mir.Die meisten Währungen werden zitiert, um vier oder fünf Dezimalstellen.Ich kenne Situationen, in denen dezimal-Skala von 8 (oder mehr) ist erforderlich, aber dies ist, wo ein "normales" Geldbetrag (sagen wir vier Dezimalstellen) wurde pro rata würde, was der Nachkommastellen sollte entsprechend reduziert werden (betrachten Sie auch eine floating-point-Typ in solchen Umständen).Und niemand hat so viel Geld, das heutzutage zu verlangen Nachkommastellen 24 :)

Doch anstatt eine one-size-fits-all " - Ansatz, der einige der Forschung vielleicht in Ordnung zu sein.Fragen Sie Ihren designer oder domain-Experten um die Buchhaltung Regeln gelten können:GAAP, EU, etc.Ich vage erinnern einige EU-intra-Staatliche transfers mit expliziten Regeln für die Rundung auf fünf Dezimalstellen, daher ist DECIMAL(p, 6) für die Lagerung.Buchhalter im Allgemeinen scheinen zu bevorzugen, die auf vier Dezimalstellen.


PS Vermeiden, SQL-Server MONEY Daten, die Art, weil Sie hat ernsthafte Probleme mit der Genauigkeit bei der Rundung, unter anderen überlegungen wie Portabilität etc.Finden Aaron Bertrand ' s blog.


Microsoft und Sprache wählte Designern banker ' s rounding, weil die hardware-Designer wählte es [Zitat?].Sie ist verankert in der Institute of Electrical and Electronics Engineers (IEEE) standards, zum Beispiel.Und hardware-Designer wählte es, weil Mathematiker bevorzugen es.Finden Wikipedia;paraphrase:Die 1906 edition von Wahrscheinlichkeit und Theorie der Fehler genannt das "computer s rule" ("Computer", was bedeutet Menschen, die Berechnungen durchzuführen).

Andere Tipps

Wir führten vor kurzem ein System, das Werte in mehreren Währungen zu handhaben muss und konvertieren zwischen ihnen und dachte, ein paar Dinge, auf die harte Tour.

Verwenden Sie niemals Gleitkommazahlen FOR MONEY

Gleitkomma-Arithmetik führt Ungenauigkeiten, die nicht bemerkt werden kann, bis sie etwas nach oben geschraubt haben. Alle Werte sollten entweder als ganze Zahlen oder Fest Dezimaltypen gespeichert werden, und wenn Sie eine Fest Dezimal-Typ verwenden wählen dann stellen Sie sicher, dass Sie genau verstehen, was diese Art tut unter der Haube (dh nicht intern es verwenden, um eine ganze oder Gleitkomma- Typ).

Wenn Sie brauchen Berechnungen oder Konvertierungen zu tun:

  1. Konvertieren Werte Gleitkomma
  2. Berechne neuen Wert
  3. Rund um die Zahl und wandeln es wieder in eine ganze Zahl

Wenn Sie eine Fließkommazahl zurück auf eine ganze Zahl in Schritt 3 Umwandlung, wirft es nicht nur - eine mathematische Funktion verwenden Sie es zuerst runden. Dies wird in der Regel round werden, obwohl in besonderen Fällen könnte es floor oder ceil werden. Kennen Sie den Unterschied und wählen sorgfältig aus.

Speichern Sie den Typ einer Zahl neben dem Wert

Dies ist vielleicht nicht so wichtig für Sie sein, wenn Sie nur eine Währung Handhabung, aber es war wichtig, dass wir in mehreren Währungen Handhabung. Wir haben das 3-stelligen Code für eine Währung wie USD, GBP, JPY, EUR, etc.

Je nach Situation ist es auch hilfreich sein, zu speichern:

  • Ob die Zahl vor oder nach Steuern (und was der Steuersatz war)
  • Ob die Zahl ist das Ergebnis einer Umwandlung (und was es umgewandelt wurde aus)

Kennen Sie die Genauigkeit Grenzen der Zahlen mit Ihnen zu tun hat

Für echte Werte, die Sie wollen als die kleinste Einheit der Währung genau sein. Dies bedeutet, dass Sie keine Werte kleiner als ein Cent haben, einen Pfennig, ein Yen, ein Fen usw. Sie nicht Werte speichern mit einer höheren Genauigkeit als die ohne Grund.

Intern können Sie wählen, mit kleineren Werten befassen, in dem Fall, dass eine andere Art von Währungswert . Stellen Sie sicher, dass Ihr Code weiß, was was ist und nicht bekommen sie gemischt. Vermeiden Sie auch hier Gleitkommazahlen.


diese Regeln alle zusammen Hinzufügen, haben wir beschlossen, auf den folgenden Regeln. Im laufenden Code, werden Währungen unter Verwendung einer ganzen Zahl für die kleinste Einheit gespeichert.

class Currency {
   String code;       //  eg "USD"
   int value;         //  eg 2500
   boolean converted;
}

class Price {
   Currency grossValue;
   Currency netValue;
   Tax taxRate;
}

In der Datenbank werden die Werte als String in folgendem Format gespeichert:

USD:2500

, die den Wert von $ 25,00 speichern. Wir konnten zeigen, dass nur das tun, weil der Code, der mit Währungen befasst muss nicht innerhalb der Datenbank-Ebene sein, selbst, so können alle Werte zunächst in den Speicher umgewandelt werden. Andere Situationen wird ohne Zweifel eignen sich für andere Lösungen.


Und für den Fall, dass ich nicht machen deutlich früher, Sie schwimmen nicht verwenden!

Wenn das Geld in MySQL der Handhabung von DECIMAL (13,2), wenn Sie die Genauigkeit Ihrer Geldwerte kennen oder DOUBLE verwenden, wenn Sie nur eine schnelle gut genug Näherungswert wollen. Also, wenn Ihr Antrag Geld zu einer Billion Dollar-Werte bis zu handhaben muss (oder Euro oder Pfund), dann sollte diese Arbeit:

DECIMAL(13, 2)

Oder, wenn Sie müssen erfüllen GAAP dann verwenden:

DECIMAL(13, 4)

4 Dezimalstellen würden Sie die Genauigkeit der kleinsten Währungsuntereinheiten der Welt zu speichern. Sie können es weiter nach unten, wenn Sie Micropayment (nanopayment ?!) Genauigkeit benötigen.

Ich ziehe es zu DECIMAL zu DBMS-spezifischen Geldarten, sind Sie sicherer IMO diese Art von Logik in der Anwendung zu halten. Ein weiterer Ansatz auf der gleichen Linie ist einfach eine [lang] integer zu verwenden, mit der Formatierung in ¤unit.subunit für die menschliche Lesbarkeit (¤ = Währungssymbol) auf der Anwendungsebene.

Der Geld-Datentyp auf SQL Server verfügt über vier Stellen hinter dem Komma.

Von SQL Server 2000-Online:

Währungsdaten repräsentieren positive oder negative Geldbeträge. In Microsoft® SQL Server ™ 2000 wird die Gelddaten gespeichert, das Geld und smallmoney- Datentypen verwenden. Monetäre Daten können mit einer Genauigkeit von vier Nachkommastellen gespeichert werden. Verwenden Sie den Geld Datentyp zum Speichern von Werten im Bereich von -922,337,203,685,477.5808 durch +922,337,203,685,477.5807 (8 Bytes erfordert einen Wert zu speichern). Verwenden Sie den smallmoney- Datentyp zum Speichern von Werten im Bereich von -214,748.3648 durch 214,748.3647 (4 Bytes erfordert einen Wert zu speichern). Wenn eine größere Anzahl von Dezimalstellen benötigt werden, anstatt den Dezimal-Datentyp verwenden.

In einigen Fällen müssen Sie als ein Cent weniger gehen und es gibt internationale Währungen, die sehr große demoniations verwenden. Zum Beispiel könnten Sie Ihre Kunden 0,088 Cent pro Transaktion berechnen. In meiner Oracle-Datenbank werden die Spalten als NUMBER definiert (20,4)

Wenn Sie vorhaben, in der DB jede Art von arithmetischen Operationen zu tun (Verrechnungssätze multipliziert und so weiter), werden Sie wahrscheinlich wollen viel mehr Präzision als die Menschen hier sind darauf hindeutet, aus den gleichen Gründen, die Sie Würd will nie etwas verwenden, weniger als eine doppelte Genauigkeit Gleitkommawert im Anwendungscode.

Wenn Sie IBM Informix Dynamic Server verwendet haben, würden Sie eine Geld-Typ haben, die eine kleinere Variante des DECIMAL oder NUMERIC-Typ ist. Es ist immer eine Festkommatyp (während DECIMAL kann ein Gleitkomma-Typ sein). Sie können eine Skala von 1 bis 32 angegeben, und eine Genauigkeit von 0 bis 32 (auf einer Skala von 16 säumige und einer Genauigkeit von 2). Also, je nachdem, was Sie speichern müssen, können Sie DECIMAL (16,2) verwenden - immer noch groß genug, um die US Federal Deficit zu halten, auf den nächsten Cent - oder Sie können einen kleineren Bereich oder mehr Dezimalstellen verwenden

Ich würde denken, dass für einen großen Teil Ihrer oder Anforderungen Ihrer Kunden sollten diktieren, welche Genauigkeit und Maßstab zu verwenden. Zum Beispiel für die E-Commerce-Website, die ich auf, dass ich Arbeit beschäftigt sich mit Geld in GBP nur, ich habe es Dezimal erforderlich gewesen zu halten (6, 2).

Eine späte Antwort hier, aber ich habe verwendet

DECIMAL(13,2)

, die ich recht in der Annahme bin, soll bis zu 99,999,999,999.99 ermöglichen.

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