Ich verwende eine Dezimalspalte, um Geldwerte in einer Datenbank zu speichern, und heute habe ich mich gefragt, welche Präzision und Skalierung ich verwenden soll.
Da angeblich char-Spalten mit fester Breite effizienter sind, dachte ich, dass dies auch für Dezimalspalten gelten könnte. Ist es?
Und welche Präzision und Skalierung sollte ich verwenden? Ich dachte rund um die Uhr an Präzision. Ist das übertrieben, nicht genug oder in Ordnung?
Folgendes habe ich beschlossen:
- Speichern Sie die Conversion-Raten (falls zutreffend) in der Transaktionstabelle selbst als Float
- Speichern Sie die Währung in der Kontotabelle
- Der Transaktionsbetrag beträgt a
DECIMAL(19,4)
- Alle Berechnungen mit einer Conversion-Rate werden von meiner Anwendung verarbeitet, sodass ich die Kontrolle über Rundungsprobleme behalten kann
Ich denke nicht, dass ein Float für die Conversion-Rate ein Problem ist, da es hauptsächlich als Referenz dient, und ich werde es trotzdem auf eine Dezimalstelle umwandeln.
Vielen Dank für Ihre wertvollen Beiträge.
DECIMAL(19, 4)
Dies ist eine beliebte Wahl. Überprüfen Sie dies auch hier. Weltwährungsformate, um zu entscheiden, wie viele Dezimalstellen verwendet werden sollen. Hoffnung hilft.Antworten:
Wenn Sie auf der Suche nach einer Einheitsgröße sind, würde ich vorschlagen, dass dies
DECIMAL(19, 4)
eine beliebte Wahl ist (ein schnelles Google bestätigt dies). Ich denke, dies stammt aus dem alten Datentyp VBA / Access / Jet Currency, der der erste Festkomma-Dezimaltyp in der Sprache ist.Decimal
wurde nur in VB6 / VBA6 / Jet 4.0 im Stil der Version 1.0 (dh nicht vollständig implementiert) geliefert.Als Faustregel für die Speicherung von Festkomma-Dezimalwerten gilt, dass mindestens eine Dezimalstelle mehr gespeichert wird, als Sie tatsächlich benötigen, um das Runden zu ermöglichen. Einer der Gründe für die Zuordnung des alten
Currency
Typs im vorderen Ende zumDECIMAL(19, 4)
Typ im hinteren Ende war, dass dieCurrency
Banker von Natur ausDECIMAL(p, s)
gerundet waren , während sie durch Abschneiden gerundet waren.Eine zusätzliche Dezimalstelle im Speicher für
DECIMAL
ermöglicht die Implementierung eines benutzerdefinierten Rundungsalgorithmus, anstatt die Standardeinstellung des Anbieters zu übernehmen (und die Rundung der Banker ist, gelinde gesagt, alarmierend, wenn ein Designer erwartet, dass alle Werte, die mit 0,5 enden, von Null abrunden). .Ja,
DECIMAL(24, 8)
klingt für mich nach Overkill. Die meisten Währungen werden mit vier oder fünf Dezimalstellen angegeben. Ich kenne Situationen, in denen eine Dezimalskala von 8 (oder mehr) erforderlich ist , aber hier wurde ein „normaler“ Geldbetrag (z. B. vier Dezimalstellen) anteilig festgelegt, was bedeutet, dass die Dezimalgenauigkeit entsprechend reduziert werden sollte (auch berücksichtigen) ein Gleitkommatyp unter solchen Umständen). Und heutzutage hat niemand mehr so viel Geld, um eine Dezimalgenauigkeit von 24 zu verlangen :)Anstelle eines einheitlichen Ansatzes sind jedoch möglicherweise einige Untersuchungen angebracht. Fragen Sie Ihren Designer oder Domain-Experten nach den möglicherweise geltenden Rechnungslegungsvorschriften: GAAP, EU usw. Ich erinnere mich vage an einige innerstaatliche EU-Überweisungen mit expliziten Regeln für das Runden auf fünf Dezimalstellen, die daher
DECIMAL(p, 6)
zur Speicherung verwendet werden. Buchhalter scheinen im Allgemeinen vier Dezimalstellen zu bevorzugen.PS Vermeiden Sie den
MONEY
Datentyp von SQL Server, da er beim Runden schwerwiegende Probleme mit der Genauigkeit aufweist, unter anderem bei der Portabilität usw. Siehe Aaron Bertrands Blog .Microsoft und Sprachdesigner haben sich für die Rundung von Bankern entschieden, weil Hardware-Designer sie gewählt haben [Zitat?]. Es ist beispielsweise in den Standards des Institute of Electrical and Electronics Engineers (IEEE) verankert. Und Hardware-Designer haben es gewählt, weil Mathematiker es bevorzugen. Siehe Wikipedia ; Um es zu paraphrasieren: Die Ausgabe von 1906 von Probability and Theory of Errors nannte dies "die Regel des Computers" ("Computer" bedeutet Menschen, die Berechnungen durchführen).
quelle
DECIMAL(19, 4)
beliebter alsDECIMAL(19, 2)
? Die meisten Weltwährungen sind nur zwei Dezimalstellen.Wir haben kürzlich ein System implementiert, das Werte in mehreren Währungen verarbeiten und zwischen ihnen umrechnen muss, und einige Dinge auf die harte Tour herausgefunden.
NIEMALS SCHWIMMENDE PUNKTNUMMERN FÜR GELD VERWENDEN
Gleitkomma-Arithmetik führt zu Ungenauigkeiten, die möglicherweise erst bemerkt werden, wenn sie etwas vermasselt haben. Alle Werte sollten entweder als Ganzzahlen oder als Typen mit festen Dezimalstellen gespeichert werden. Wenn Sie sich für die Verwendung eines Typs mit festen Dezimalstellen entscheiden, stellen Sie sicher, dass Sie genau verstehen, was dieser Typ unter der Haube tut (dh intern eine Ganzzahl oder einen Gleitkomma verwendet Art).
Wenn Sie Berechnungen oder Konvertierungen durchführen müssen:
Wenn Sie eine Gleitkommazahl in Schritt 3 wieder in eine Ganzzahl konvertieren, wandeln Sie sie nicht einfach um - verwenden Sie eine mathematische Funktion, um sie zuerst zu runden. Dies wird normalerweise sein
round
, obwohl es in besonderen Fällen sein könntefloor
oderceil
. Kennen Sie den Unterschied und wählen Sie sorgfältig.Speichern Sie den Typ einer Zahl neben dem Wert
Dies ist für Sie möglicherweise nicht so wichtig, wenn Sie nur eine Währung abwickeln, aber für uns war es wichtig, mehrere Währungen abzuwickeln. Wir haben den dreistelligen Code für eine Währung wie USD, GBP, JPY, EUR usw. verwendet.
Je nach Situation kann es auch hilfreich sein, Folgendes zu speichern:
Kennen Sie die Genauigkeitsgrenzen der Zahlen, mit denen Sie es zu tun haben
Für reale Werte möchten Sie so genau sein wie die kleinste Einheit der Währung. Dies bedeutet, dass Sie keine Werte haben, die kleiner als ein Cent, ein Penny, ein Yen, ein Fen usw. sind. Speichern Sie Werte nicht ohne Grund mit höherer Genauigkeit.
Intern können Sie sich für kleinere Werte entscheiden. In diesem Fall handelt es sich um eine andere Art von Währungswert . Stellen Sie sicher, dass Ihr Code weiß, welcher welcher ist, und dass er sie nicht verwechselt. Vermeiden Sie auch hier die Verwendung von Gleitkommawerten.
Wenn wir all diese Regeln zusammenfassen, haben wir uns für die folgenden Regeln entschieden. Im laufenden Code werden Währungen mit einer Ganzzahl für die kleinste Einheit gespeichert.
In der Datenbank werden die Werte als Zeichenfolge im folgenden Format gespeichert:
Das speichert den Wert von 25,00 $. Dies war nur möglich, weil sich der Code, der sich mit Währungen befasst, nicht in der Datenbankebene selbst befinden muss, sodass alle Werte zuerst in den Speicher konvertiert werden können. Andere Situationen eignen sich zweifellos für andere Lösungen.
Und falls ich es vorher nicht klar gemacht habe, benutze keinen Float!
quelle
bigint
ob Sie nach dem Betrag sortieren möchten . Und verschwenden Sie nicht Ihre Zeit mit PHP 32bit, wenn Sie mit großen ganzen Zahlen arbeiten, aktualisieren Sie auf 64bit oder Node.JS;)Verwenden Sie beim Umgang mit Geld in MySQL DECIMAL (13,2), wenn Sie die Genauigkeit Ihrer Geldwerte kennen, oder DOUBLE, wenn Sie nur einen schnellen, ausreichend guten ungefähren Wert wünschen. Wenn Ihre Anwendung also Geldwerte bis zu einer Billion Dollar (oder Euro oder Pfund) verarbeiten muss, sollte dies funktionieren:
Wenn Sie GAAP einhalten müssen, verwenden Sie:
quelle
Mit 4 Dezimalstellen können Sie die kleinsten Währungsuntereinheiten der Welt genau speichern. Sie können es weiter reduzieren, wenn Sie eine Genauigkeit der Mikrozahlung (Nanopayment?!) Benötigen.
Auch ich bevorzuge
DECIMAL
DBMS-spezifische Geldarten. Sie können diese Logik sicherer in der IMO-Anwendung beibehalten. Ein anderer Ansatz in die gleiche Richtung besteht einfach darin, eine [lange] Ganzzahl zu verwenden, wobei die Formatierung in ¤unit.subunit für die menschliche Lesbarkeit (¤ = Währungssymbol) auf Anwendungsebene erfolgt.quelle
Der Gelddatentyp in SQL Server hat vier Nachkommastellen.
Aus SQL Server 2000 Books Online:
Gelddaten repräsentieren positive oder negative Geldbeträge. In Microsoft® SQL Server ™ 2000 werden Gelddaten unter Verwendung der Datentypen Geld und Kleingeld gespeichert. Gelddaten können mit einer Genauigkeit von vier Dezimalstellen gespeichert werden. Verwenden Sie den Gelddatentyp, um Werte im Bereich von -922.337.203.685.477.5808 bis +922.337.203.685.477.5807 zu speichern (zum Speichern eines Werts sind 8 Byte erforderlich). Verwenden Sie den Datentyp smallmoney, um Werte im Bereich von -214.748,3648 bis 214.748,3647 zu speichern (zum Speichern eines Werts sind 4 Byte erforderlich). Wenn eine größere Anzahl von Dezimalstellen erforderlich ist, verwenden Sie stattdessen den Dezimaldatentyp.
quelle
Manchmal müssen Sie auf weniger als einen Cent gehen, und es gibt internationale Währungen, die sehr große Dämonisierungen verwenden. Beispielsweise können Sie Ihren Kunden 0,088 Cent pro Transaktion in Rechnung stellen. In meiner Oracle-Datenbank sind die Spalten als NUMBER (20,4) definiert.
quelle
Wenn Sie in der Datenbank arithmetische Operationen ausführen (Abrechnungsraten multiplizieren usw.), möchten Sie wahrscheinlich viel mehr Präzision, als die Leute hier vorschlagen, aus den gleichen Gründen, die Sie niemals hätten Sie möchten weniger als einen Gleitkommawert mit doppelter Genauigkeit im Anwendungscode verwenden.
quelle
BigDecimal
), aber lange Zeit war es doppelte Präzision (denkendouble
stattfloat
). Willkürliche Präzision hat in einigen Fällen auch erhebliche Leistungseinbußen. Testen ist definitiv der richtige Ansatz.Wenn Sie IBM Informix Dynamic Server verwenden, haben Sie einen MONEY-Typ, der eine geringfügige Variante des DECIMAL- oder NUMERIC-Typs darstellt. Es ist immer ein Festkommatyp (während DECIMAL ein Gleitkommatyp sein kann). Sie können eine Skala von 1 bis 32 und eine Genauigkeit von 0 bis 32 angeben (standardmäßig eine Skala von 16 und eine Genauigkeit von 2). Je nachdem, was Sie speichern müssen, können Sie DECIMAL (16,2) verwenden - immer noch groß genug, um das US-Bundesdefizit auf den nächsten Cent genau zu halten - oder Sie können einen kleineren Bereich oder mehr Dezimalstellen verwenden.
quelle
Ich würde denken, dass Ihre oder die Anforderungen Ihres Kunden zu einem großen Teil bestimmen sollten, welche Präzision und Skalierung verwendet werden soll. Für die E-Commerce-Website, an der ich gerade arbeite und die sich nur mit Geld in GBP befasst, musste ich sie auf Dezimal (6, 2) halten.
quelle
Eine späte Antwort hier, aber ich habe verwendet
was ich richtig denke, sollte bis zu 99.999.999.999,99 erlauben.
quelle