NUMERIC
/DECIMAL
Som Joachim Isaksson sa
, vill du använda NUMERIC
/DECIMAL
typ, som en godtycklig precisionstyp.
Två viktiga punkter om NUMERIC
/DECIMAL
:
- Läs dokumentet noggrant för att lära dig att du bör specificera skalan för att undvika standardskalan 0, vilket betyder heltalsvärden där decimalbråket avbryts. Även om detta är en av platserna där Postgres avviker från standard SQL (vilket ger dig vilken skala som helst upp till implementeringsgränsen). Så att inte specificera skalan är ett dåligt val.
- SQL-typerna
NUMERIC
&DECIMAL
är nära men inte identiska enligt SQL Standard. I SQL:92 , din specificerade precision förNUMERIC
respekteras, medan förDECIMAL
databasservern tillåts lägga till ytterligare precision utöver vad du angav. Även här avviker Postgres lite från standarden, med bådeNUMERIC
&DECIMAL
dokumenterad som likvärdig.
Villkor:
- Precision är det totala antalet siffror i ett tal.
- Skala är antalet siffror till höger om decimaltecknet (decimalbråket).
- ( Precision - Skala ) =Antal siffror till vänster om decimalkomma (heltalsdel).
Var tydlig med ditt projekts specifikationer för precision och skala:
- Stor
Precisionen måste vara tillräckligt stor för att hantera större antal som kan behövas i framtiden. Mening... Kanske din app idag fungerar i mängder av tusentals USD men måste i framtiden utföra sammandragningsrapporter som hamnar i miljoner. - Liten
För vissa redovisningsändamål kan du behöva lagra en bråkdel av ett minsta valutabelopp. Det betyder... Mer än 3 eller 4 decimaler istället för de 2 som behövs för en slant i USD .
Undvik MONEY
typ
Postgres erbjuder en MONEY
typ också. Det kan låta rätt, men förmodligen inte bäst för de flesta ändamål. En nackdel är det med MONEY
skalan ställs in av en databasomfattande konfigurationsinställning baserat på locale
. Så den inställningen kan variera farligt lätt när du byter server eller gör andra ändringar. Dessutom kan du inte styra den inställningen för specifika kolumner, medan du kan ställa in skalan för varje kolumn i NUMERIC
typ. Till sist, MONEY
är inte standard SQL som visas i denna lista över standard SQL-data typer
. Postgres inkluderar MONEY
för att underlätta för folk som porterar data från andra databassystem.
Flytta decimalkomma
Ett annat alternativ som används av vissa är att flytta decimaltecknet, och bara lagra i stora heltalsdatatyp.
Till exempel, om du lagrar USD dollar till öre, multiplicera ett givet bråktal med 100, kasta till en heltalstyp och fortsätt. Till exempel, $123,45 blir heltal 12 345.
Fördelen med detta tillvägagångssätt är snabbare exekveringstider. Operationer som sum
är mycket snabba när de utförs på heltal. En annan fördel med heltal är mindre minnesanvändning.
Jag tycker att det här tillvägagångssättet är irriterande, förvirrande och riskabelt. Irriterande eftersom datorer borde fungera för oss, inte mot oss. Risk eftersom någon programmerare eller användare kan försumma att multiplicera/dividera för att konvertera tillbaka till bråktal, vilket ger felaktiga resultat. Om du arbetar i ett system utan bra stöd för korrekta bråktal kan detta tillvägagångssätt vara en acceptabel lösning.
Jag ser ingen fördel med att flytta decimalkomma när vi har DECIMAL
/NUMERIC
i SQL och BigDecimal
i Java.
Avrundning &NaN
I appens programmering, såväl som alla beräkningar som görs på Postgres serversida, var mycket försiktig och medveten om avrundning och trunkering i decimalbråket. Och testa för oavsiktlig NaNs dyker upp.
På båda sidor, app och Postgres, undvik alltid flytande punkt datatyper för pengar fungerar. Flytpunkt är designad för prestandahastighet , men till kostnaden för noggrannhet . Beräkningar kan resultera i till synes galna extrasiffror i decimalbråket. Inte bra för ekonomiska/pengar eller andra ändamål där noggrannhet spelar roll.
BigDecimal
Ja, i Java vill du ha BigDecimal
som din godtyckliga precisionstyp. BigDecimal
är långsammare och använder mer minne, men kommer att lagra dina pengar korrekt. SQL NUMERIC
/DECIMAL
ska mappas till BigDecimal
som diskuterats här
och på StackOverflow
.
BigDecimal
är en av de bästa sakerna med Java. Jag känner inte till någon annan plattform med en liknande klass, särskilt en så välimplementerad och välslipad med stora förbättringar och korrigeringar som gjorts under åren.
Använder BigDecimal
är definitivt långsammare än att använda Javas flyttalstyper
, float
&double
. Men i appar i verkligheten tvivlar jag på att dina pengarberäkningar kommer att vara någon flaskhals. Och dessutom, vilken vill du eller dina kunder ha:den snabbaste pengaberäkningar, eller korrekta pengar beräkningar? 😉
Jag har alltid tänkt på BigDecimal
som den största sleeper-funktionen i Java, den viktigaste fördelen med att använda Java-plattformen framför så många andra plattformar som saknar så sofistikerat stöd för bråktal.
Liknande fråga:Bästa datatyp för valuta