NUMERIC
/DECIMAL
Jak řekl Joachim Isaksson
, chcete použít NUMERIC
/DECIMAL
typu jako libovolný přesný typ.
Dva důležité body o NUMERIC
/DECIMAL
:
- Přečtěte si dokument pečlivě, abyste zjistili, že byste měli určit měřítko, abyste se vyhnuli výchozímu měřítku 0, což znamená celočíselné hodnoty, kde je desetinný zlomek odříznut. I když toto je jedno z míst, kde se Postgres odchyluje od standardního SQL (což vám dává jakékoli měřítko až do limitu implementace). Takže neuvedení měřítka je špatná volba.
- Typy SQL
NUMERIC
&DECIMAL
jsou blízké, ale nejsou totožné podle standardu SQL. V SQL:92 , vámi zadaná přesnost proNUMERIC
je respektováno, zatímco proDECIMAL
databázovému serveru je povoleno přidat další přesnost nad rámec toho, co jste zadali. Zde se Postgres opět trochu vymyká standardu, s oběmaNUMERIC
&DECIMAL
zdokumentováno jako ekvivalent.
Podmínky:
- Přesnost je celkový počet číslic v čísle.
- Měřítko je počet číslic napravo od desetinné čárky (desetinný zlomek).
- ( Přesnost – Měřítko ) =Počet číslic nalevo od desetinné čárky (celá část).
Ujasněte si specifikace vašeho projektu pro přesnost a měřítko:
- Velký
Přesnost musí být dostatečně velká, aby zvládla větší čísla, která mohou být v budoucnu zapotřebí. To znamená... Možná, že vaše aplikace dnes funguje v řádech tisíců USD, ale v budoucnu musí provádět souhrnné přehledy, které skončí v milionech. - Malý
Pro některé účetní účely možná budete muset uložit zlomek nejmenší částky v měně. To znamená… Více než 3 nebo 4 desetinná místa namísto 2 potřebných pro cent v USD .
Vyhněte se MONEY
typ
Postgres nabízí MONEY
typ také. To může znít správně, ale pravděpodobně to není nejlepší pro většinu účelů. Jedna nevýhoda je, že s MONEY
škála je nastavena nastavením konfigurace pro celou databázi na základě místního prostředí
. Toto nastavení se tedy může nebezpečně snadno měnit, když přepínáte servery nebo provádíte jiné změny. Kromě toho nemůžete toto nastavení ovládat pro konkrétní sloupce, zatímco můžete nastavit měřítko pro každý sloupec NUMERIC
typ. Nakonec MONEY
není standardní SQL, jak je uvedeno v tomto seznamu standardních dat SQL typy
. Postgres zahrnuje MONEY
pro pohodlí lidí, kteří přenášejí data z jiných databázových systémů.
Přesuňte desetinnou čárku
Další alternativou, kterou někteří používají, je přesunutí desetinné čárky a uložení ve velkém celočíselném datovém typu.
Pokud například ukládáte USD dolarů na cent, vynásobte libovolné dané zlomkové číslo 100, přetypujte na typ celé číslo a pokračujte. Například 123,45 $ se stane celým číslem 12 345.
Výhodou tohoto přístupu je rychlejší provedení. Operace jako sum
jsou velmi rychlé při provádění na celá čísla. Další výhodou celých čísel je menší využití paměti.
Tento přístup mi připadá otravný, matoucí a riskantní. Nepříjemné, protože počítače by měly fungovat pro nám, ne proti nám. Riskantní, protože některý programátor nebo uživatel může zanedbávat násobení/dělení, aby převedl zpět na zlomkové číslo, což dává nesprávné výsledky. Pokud pracujete v systému bez dobré podpory přesných zlomkových čísel, může být tento přístup přijatelným řešením.
Nevidím žádnou výhodu v posunutí desetinné čárky, když máme DECIMAL
/NUMERIC
v SQL a BigDecimal
v Javě.
Zaokrouhlení a NaN
Při programování vaší aplikace a také při jakýchkoli výpočtech prováděných na straně serveru Postgres buďte velmi opatrní a uvědomte si zaokrouhlování a zkracování v desetinném zlomku. A test na neúmyslné NaN vyskakující.
Na obou stranách, v aplikaci i v Postgresu, se vždy vyhněte plovoucí desetinná čárka datové typy pro práci s penězi. Plovoucí desetinná čárka je navržena pro rychlost výkonu , ale za náklady na přesnost . Výpočty mohou mít za následek zdánlivě šílené další číslice v desetinném zlomku. Není vhodné pro finanční/peněžní účely nebo jiné účely, kde záleží na přesnosti.
BigDecimal
Ano, v Javě chcete BigDecimal
jako váš libovolný typ přesnosti. BigDecimal
je pomalejší a využívá více paměti, ale přesně uloží vaše peněžní částky. SQL NUMERIC
/DECIMAL
by se měl namapovat na BigDecimal
jak je uvedeno zde
a na StackOverflow
.
BigDecimal
je jedna z nejlepších věcí na Javě. Nevím o žádné jiné platformě s podobnou třídou, zvláště o tak dobře implementované a vypilované s velkými vylepšeními a opravami provedenými v průběhu let.
Pomocí BigDecimal
je rozhodně pomalejší než použití typů Java s plovoucí desetinnou čárkou
, float
&double
. Ale v aplikacích v reálném světě pochybuji, že vaše výpočty peněz budou překážkou. A kromě toho, co vy nebo vaši zákazníci chcete:nejrychlejší výpočty peněz nebo přesné výpočty peněz? 😉
Vždy jsem myslel na BigDecimal
jako největší funkce spánku v Javě, nejdůležitější výhoda používání platformy Java oproti mnoha jiným platformám, které postrádají tak sofistikovanou podporu pro zlomková čísla.
Podobná otázka:Nejlepší datový typ pro měnu