NUMERIC
/DECIMAL
Som Joachim Isaksson sagde
, vil du bruge NUMERIC
/DECIMAL
type, som en vilkårlig præcisionstype.
To vigtige punkter om NUMERIC
/DECIMAL
:
- Læs dokumentet omhyggeligt for at lære, at du bør angive skalaen for at undgå standardskalaen på 0, hvilket betyder heltalsværdier, hvor decimalbrøken bliver fjernet. Selvom dette er et af de steder, hvor Postgres afviger fra standard SQL (giver dig enhver skala op til implementeringsgrænsen). Så det er et dårligt valg at undlade at angive skalaen.
- SQL-typerne
NUMERIC
&DECIMAL
er tætte, men ikke identiske i henhold til SQL-standarden. I SQL:92 , din specificerede præcision forNUMERIC
respekteres, hvorimod forDECIMAL
databaseserveren har lov til at tilføje yderligere præcision ud over, hvad du har angivet. Her afviger Postgres igen en smule fra standarden, med bådeNUMERIC
&DECIMAL
dokumenteret som tilsvarende.
Vilkår:
- Nøjagtighed er det samlede antal cifre i et tal.
- Skala er antallet af cifre til højre for decimaltegnet (decimalbrøken).
- ( Præcision - Skala ) =Antal cifre til venstre for decimalkomma (heltalsdel).
Vær klar over dit projekts specifikationer for præcision og skala:
- Stor
Præcisionen skal være stor nok til at kunne håndtere større antal, der måtte blive brug for i fremtiden. Betydning... Måske fungerer din app i dag i mængder af tusindvis af USD, men skal i fremtiden udføre roll-up rapporter, der ender i millioner. - Lille
Til nogle regnskabsmæssige formål skal du muligvis gemme en brøkdel af det mindste valutabeløb. Det betyder... Mere end 3 eller 4 decimaler i stedet for de 2, der er nødvendige for en krone i USD .
Undgå MONEY
type
Postgres tilbyder en MONEY
type også. Det lyder måske rigtigt, men nok ikke bedst til de fleste formål. En ulempe er det med MONEY
skalaen er indstillet af en konfigurationsindstilling for hele databasen baseret på locale
. Så den indstilling kan nemt variere farligt, når du skifter server eller foretager andre ændringer. Desuden kan du ikke kontrollere denne indstilling for specifikke kolonner, mens du kan indstille skalaen på hver kolonne af NUMERIC
type. Til sidst, MONEY
er ikke standard SQL som vist i denne liste over standard SQL-data typer
. Postgres inkluderer MONEY
for at gøre det lettere for folk, der overfører data fra andre databasesystemer.
Flyt decimaltegnet
Et andet alternativ, der anvendes af nogle, er at flytte decimaltegnet og bare gemme i datatypen med stort heltal.
For eksempel, hvis du gemmer USD dollars til penny, multiplicer et givet brøktal med 100, kast til en heltalstype, og fortsæt. For eksempel bliver $123,45 til heltal 12.345.
Fordelen ved denne tilgang er hurtigere eksekveringstider. Operationer såsom sum
er meget hurtige, når de udføres på heltal. En anden fordel for heltal er mindre hukommelsesforbrug.
Jeg finder denne tilgang irriterende, forvirrende og risikabel. Irriterende, fordi computere burde arbejde for os, ikke imod os. Risikabelt, fordi en programmør eller bruger kan undlade at gange/dividere for at konvertere tilbage til brøktal, hvilket giver forkerte resultater. Hvis du arbejder i et system uden god understøttelse af nøjagtige brøktal, kan denne fremgangsmåde være en acceptabel løsning.
Jeg kan ikke se nogen fordel ved at flytte decimaltegnet, når vi har DECIMAL
/NUMERIC
i SQL og BigDecimal
i Java.
Afrunding og NaN
I din apps programmering såvel som i alle beregninger foretaget på Postgres-serversiden skal du være meget forsigtig og opmærksom på afrunding og trunkering i decimalbrøken. Og test for utilsigtet NaNs dukker op.
På begge sider, app og Postgres, undgå altid flydende komma datatyper for penge arbejde. Flydende komma er designet til ydelseshastighed , men på bekostning af nøjagtighed . Beregninger kan resultere i tilsyneladende skøre ekstra cifre i decimalbrøken. Ikke godt til økonomiske/penge eller andre formål, hvor nøjagtighed er vigtig.
BigDecimal
Ja, i Java vil du have BigDecimal
som din vilkårlige præcisionstype. BigDecimal
er langsommere og bruger mere hukommelse, men vil præcist gemme dine pengebeløb. SQL NUMERIC
/DECIMAL
skal kortlægges til BigDecimal
som diskuteret her
og på StackOverflow
.
BigDecimal
er en af de bedste ting ved Java. Jeg kender ikke nogen anden platform med en lignende klasse, især en så velimplementeret og veludviklet med store forbedringer og rettelser lavet gennem årene.
Brug af BigDecimal
er bestemt langsommere end at bruge Javas flydende kommatyper
, float
&double
. Men i apps fra den virkelige verden tvivler jeg på, at dine pengeberegninger vil være nogen flaskehals. Og desuden, hvad ønsker du eller dine kunder:den hurtigste pengeberegninger eller præcise pengeberegninger? 😉
Jeg har altid tænkt på BigDecimal
som den største sovefunktion i Java, den vigtigste fordel ved at bruge Java-platformen frem for så mange andre platforme, der mangler en sådan sofistikeret understøttelse af brøktal.
Lignende spørgsmål:Bedste datatype til valuta