PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Gelddaten auf PostgreSQL mit Java

NUMERIC /DECIMAL

Wie Joachim Isaksson sagte , möchten Sie NUMERIC verwenden /DECIMAL Typ als Typ mit beliebiger Genauigkeit.

Zwei wichtige Punkte zu NUMERIC /DECIMAL :

  • Lesen Sie das Dokument sorgfältig zu lernen, dass Sie die Skalierung angeben sollten, um die Standard-Skalierung von 0 zu vermeiden, d. h. ganzzahlige Werte, bei denen der Dezimalbruch abgeschnitten wird. Dies ist zwar einer der Orte, an denen Postgres von Standard-SQL abweicht (und Ihnen eine Skalierung bis zur Implementierungsgrenze ermöglicht). Daher ist es eine schlechte Wahl, die Skala nicht anzugeben.
  • Die SQL-Typen NUMERIC &DECIMAL sind nahe, aber nicht identisch nach dem SQL-Standard. In SQL:92 , Ihre angegebene Genauigkeit für NUMERIC respektiert wird, wohingegen für DECIMAL Der Datenbankserver darf über die von Ihnen angegebene hinaus zusätzliche Genauigkeit hinzufügen. Auch hier weicht Postgres etwas vom Standard ab, sowohl mit NUMERIC &DECIMAL dokumentiert als gleichwertig.

Bedingungen:

  • Präzision ist die Gesamtzahl der Stellen in einer Zahl.
  • Skalierung ist die Anzahl der Stellen rechts vom Dezimalkomma (der Dezimalbruch).
  • ( Precision - Scale ) =Anzahl der Stellen links vom Dezimalkomma (ganzzahliger Anteil).

Stellen Sie die Spezifikationen Ihres Projekts für Präzision und Skalierung klar dar:

  • Groß
    Die Genauigkeit muss groß genug sein, um größere Zahlen zu verarbeiten, die in Zukunft benötigt werden. Das heißt… Vielleicht arbeitet Ihre App heute mit Tausenden von USD, muss aber in Zukunft Roll-up-Berichte erstellen, die in die Millionen gehen.
  • Klein
    Für einige Buchhaltungszwecke müssen Sie möglicherweise einen Bruchteil des kleinsten Währungsbetrags speichern. Das heißt… mehr als 3 oder 4 Dezimalstellen statt der 2, die für einen Penny in USD benötigt werden .

Vermeiden Sie MONEY eingeben

Postgres bietet ein MONEY Typ auch. Das mag richtig klingen, ist aber für die meisten Zwecke wahrscheinlich nicht optimal. Ein Nachteil ist das mit MONEY die Skalierung wird durch eine datenbankweite Konfigurationseinstellung festgelegt basierend auf Gebietsschema . Diese Einstellung kann also gefährlich leicht variieren, wenn Sie den Server wechseln oder andere Änderungen vornehmen. Darüber hinaus können Sie diese Einstellung nicht für bestimmte Spalten steuern, während Sie die Skalierung für jede Spalte von NUMERIC festlegen können Typ. Zum Schluss MONEY ist kein Standard-SQL, wie in dieser Liste von Standard-SQL-Daten gezeigt Typen . Postgres enthält MONEY für Leute, die Daten von anderen Datenbanksystemen portieren möchten.

Verschieben Sie den Dezimalpunkt

Eine andere Alternative, die von einigen verwendet wird, ist das Verschieben des Dezimalkommas und das Speichern in einem großen ganzzahligen Datentyp.

Zum Beispiel beim Speichern von USD Dollar in den Cent, multiplizieren Sie eine beliebige Bruchzahl mit 100, wandeln Sie sie in einen ganzzahligen Typ um und fahren Sie fort. Beispiel:123,45 $ wird zur Ganzzahl 12.345.

Der Vorteil dieses Ansatzes sind schnellere Ausführungszeiten. Operationen wie sum sind sehr schnell, wenn sie auf ganzen Zahlen ausgeführt werden. Ein weiterer Vorteil von Ganzzahlen ist die geringere Speichernutzung.

Ich finde diesen Ansatz nervig, verwirrend und riskant. Ärgerlich, weil Computer für arbeiten sollten uns, nicht gegen uns. Riskant, da einige Programmierer oder Benutzer es versäumen könnten, zu multiplizieren/dividieren, um zurück in Bruchzahlen zu konvertieren, was zu falschen Ergebnissen führt. Wenn Sie in einem System ohne gute Unterstützung für genaue Bruchzahlen arbeiten, ist dieser Ansatz möglicherweise eine akzeptable Problemumgehung.

Ich sehe keinen Vorteil darin, den Dezimalpunkt zu verschieben, wenn wir DECIMAL haben /NUMERIC in SQL und BigDecimal in Java.

Rundung &NaN

Seien Sie bei der Programmierung Ihrer App sowie bei allen Berechnungen auf der Postgres-Serverseite sehr vorsichtig und achten Sie auf Rundungen und Kürzungen im Dezimalbruch. Und testen Sie auf unbeabsichtigte NaNs auftauchen.

Vermeiden Sie auf beiden Seiten, App und Postgres, immer Floating Point Datentypen für Geldarbeit. Gleitkommazahlen sind auf Leistungsgeschwindigkeit ausgelegt , aber auf Kosten der Genauigkeit . Berechnungen können zu scheinbar verrückten zusätzlichen Ziffern im Dezimalbruch führen. Nicht gut für Finanzen/Geld oder andere Zwecke, bei denen es auf Genauigkeit ankommt.

BigDecimal

Ja, in Java möchten Sie BigDecimal als Ihren beliebigen Genauigkeitstyp. BigDecimal ist langsamer und benötigt mehr Speicher, speichert aber Ihre Geldbeträge genau. SQL NUMERIC /DECIMAL sollte BigDecimal zugeordnet werden wie hier besprochen und auf StackOverflow .

BigDecimal ist eines der besten Dinge an Java. Ich kenne keine andere Plattform mit einer ähnlichen Klasse, insbesondere keine, die so gut implementiert und ausgefeilt ist, mit wichtigen Verbesserungen und Korrekturen, die im Laufe der Jahre vorgenommen wurden.

Verwenden von BigDecimal ist definitiv langsamer als die Verwendung von Java-Gleitkommatypen , float &double . Aber in realen Apps bezweifle ich, dass Ihre Geldberechnungen ein Engpass sein werden. Und außerdem, was wollen Sie oder Ihre Kunden:das schnellste Geldberechnungen oder genau Geld rechnen? 😉

Ich habe immer an BigDecimal gedacht als das größte Schläfer-Feature in Java, der wichtigste Vorteil bei der Verwendung der Java-Plattform gegenüber so vielen anderen Plattformen, denen eine so ausgeklügelte Unterstützung für Bruchzahlen fehlt.

Ähnliche Frage:Bester Datentyp für Währung