sql >> Database >  >> RDS >> PostgreSQL

Geldgegevens op PostgreSQL met Java

NUMERIC /DECIMAL

Zoals Joachim Isaksson zei , wilt u NUMERIC gebruiken /DECIMAL type, als een willekeurig precisietype.

Twee belangrijke punten over NUMERIC /DECIMAL :

  • Lees de doc zorgvuldig om te leren dat u de schaal moet specificeren om de standaardschaal van 0 te vermijden, wat betekent dat gehele waarden waarbij de decimale breuk wordt weggelaten. Hoewel dit een van de plaatsen is waar Postgres afwijkt van standaard SQL (waardoor u enige schaalvergroting tot aan de implementatielimiet krijgt). Dus het niet specificeren van de schaal is een slechte keuze.
  • De SQL-typen NUMERIC &DECIMAL zijn dichtbij maar niet identiek volgens de SQL-standaard. In SQL:92 , uw opgegeven precisie voor NUMERIC wordt gerespecteerd, terwijl voor DECIMAL de databaseserver mag extra precisie toevoegen die verder gaat dan wat u hebt opgegeven. Ook hier wijkt Postgres een beetje af van de standaard, met zowel NUMERIC &DECIMAL gedocumenteerd als equivalent.

Voorwaarden:

  • Precisie is het totale aantal cijfers in een getal.
  • Schaal is het aantal cijfers rechts van de komma (de decimale breuk).
  • ( Precisie - Schaal ) =Aantal cijfers links van de komma (geheel getal).

Wees duidelijk over de specificaties van uw project voor precisie en schaal:

  • Groot
    De precisie moet groot genoeg zijn om grotere aantallen aan te kunnen die in de toekomst nodig kunnen zijn. Betekenis... Misschien werkt uw app vandaag de dag in bedragen van duizenden USD, maar moet hij in de toekomst overzichtsrapporten uitvoeren die in de miljoenen lopen.
  • Klein
    Voor sommige boekhoudkundige doeleinden moet u mogelijk een fractie van het kleinste valutabedrag opslaan. Betekenis... Meer dan 3 of 4 decimalen in plaats van de 2 die nodig zijn voor een cent in USD .

Vermijd MONEY typ

Postgres biedt een MONEY typ ook. Dat klinkt misschien goed, maar waarschijnlijk niet het beste voor de meeste doeleinden. Een nadeel is dat met MONEY de schaal wordt ingesteld door een database-brede configuratie-instelling gebaseerd op locale . Dus die instelling kan gevaarlijk gemakkelijk variëren wanneer u van server wisselt of andere wijzigingen aanbrengt. Bovendien kunt u die instelling niet voor specifieke kolommen bepalen, terwijl u de schaal op elke kolom van NUMERIC kunt instellen type. Ten slotte, MONEY is geen standaard SQL zoals weergegeven in deze lijst met standaard SQL-gegevens soorten . Postgres bevat MONEY voor het gemak van mensen die gegevens uit andere databasesystemen overzetten.

Verplaats het decimale punt

Een ander alternatief dat door sommigen wordt gebruikt, is het verplaatsen van de komma en gewoon opslaan in een gegevenstype met een groot geheel getal.

Als u bijvoorbeeld USD opslaat dollars tot de cent, vermenigvuldig een gegeven fractioneel getal met 100, giet het in een geheel getal en ga verder. $ 123,45 wordt bijvoorbeeld het gehele getal 12.345.

Het voordeel van deze aanpak is snellere uitvoeringstijden. Bewerkingen zoals sum zijn erg snel wanneer ze worden uitgevoerd op gehele getallen. Een ander voordeel van gehele getallen is minder geheugengebruik.

Ik vind deze aanpak vervelend, verwarrend en riskant. Vervelend omdat computers voor zouden moeten werken ons, niet tegen ons. Risicovol omdat een programmeur of gebruiker kan nalaten te vermenigvuldigen/delen om terug te zetten naar een fractioneel getal, wat onjuiste resultaten oplevert. Als u in een systeem werkt zonder goede ondersteuning voor nauwkeurige fractionele getallen, kan deze aanpak een acceptabele oplossing zijn.

Ik zie geen enkel voordeel in het verplaatsen van de komma als we DECIMAL . hebben /NUMERIC in SQL en BigDecimal in Java.

Afronding &NaN

In de programmering van uw app, evenals in alle berekeningen die op de Postgres-server zijn gemaakt, wees zeer voorzichtig en let op afronding en truncatie in de decimale breuk. En test op onbedoelde NaN's opduiken.

Aan beide kanten, app en Postgres, vermijd altijd drijvend punt gegevenstypen voor geldwerk. Drijvende punt is ontworpen voor prestatiesnelheid , maar ten koste van nauwkeurigheid . Berekeningen kunnen resulteren in schijnbaar gekke extra cijfers in de decimale breuk. Niet goed voor financiële/geldelijke of andere doeleinden waar nauwkeurigheid belangrijk is.

BigDecimal

Ja, in Java wil je BigDecimal als uw willekeurige precisietype. BigDecimal is langzamer en gebruikt meer geheugen, maar zal uw geldbedragen nauwkeurig opslaan. SQL NUMERIC /DECIMAL zou moeten verwijzen naar BigDecimal zoals besproken hier en op StackOverflow .

BigDecimal is een van de beste dingen van Java. Ik ken geen ander platform met een vergelijkbare klasse, vooral een platform dat zo goed geïmplementeerd en verfijnd is met belangrijke verbeteringen en fixes die in de loop der jaren zijn aangebracht.

BigDecimal gebruiken is zeker langzamer dan het gebruik van Java's floating-point-typen , float &double . Maar in real-world apps betwijfel ik of je geldberekeningen een knelpunt zullen zijn. En bovendien, wat willen u of uw klanten:de snelste geldberekeningen, of nauwkeurige geld berekenen?

Ik heb altijd gedacht aan BigDecimal als de grootste sleeper-functie in Java, het belangrijkste voordeel van het gebruik van het Java-platform ten opzichte van zoveel andere platforms die zulke geavanceerde ondersteuning voor fractionele getallen missen.

Vergelijkbare vraag:Beste gegevenstype voor valuta



  1. Als mysql_num_rows gelijk is aan NUL werkt NIET

  2. Maak PostgreSQL-database on-the-fly met Hibernate, zelfs als de DB niet bestaat

  3. Hoe .txt-bestanden MySQL-database op te slaan?

  4. Mysql formatteert een string zoals XXXXXXXXXXXX naar XX-XX-XXXXXXX-X