Featured image of post 在資料庫儲存貨幣金額:該用 DECIMAL 還是 BIGINT?

在資料庫儲存貨幣金額:該用 DECIMAL 還是 BIGINT?

開發金流系統時,金額該用什麼欄位存?本文深入探討為什麼絕對不要用 FLOAT,以及如何選擇 DECIMAL 或 BIGINT 來打造零誤差、高效能的貨幣儲存體系。

開發金流或電商系統,設計資料庫儲存金額欄位時,你腦中是否曾閃過「金額就用 FLOATDOUBLE 存吧」的念頭?

如果是的話,快停下你的手!你的系統可能正在偷偷漏錢。

為什麼金融系統絕對不能用浮點數?一點點看似微不足道的精度誤差,在龐大的交易量與時間累積下,可能會釀成無法挽回的災難。

那我們到底該用什麼來存錢呢?

為什麼 FLOAT 是財務系統的毒藥?

在電腦的世界裡,數字是用二進位表示的。FLOAT(浮點數)在表示某些十進位小數時,其實是一種「近似值」。這就像是你試圖用一把粗糙的電鋸去切精緻的蛋糕,不管你怎麼小心,邊緣總會掉下一些屑屑。

最經典的例子就是:0.1 + 0.2 在電腦裡往往不等於 0.3。如果你處理的是幾百萬筆交易,這些「0.00000000000000004」的微小誤差累積起來,帳面就永遠對不齊了。記住:

在金錢面前,任何「近似值」都是災難。

會計師的精緻帳本:DECIMAL 的優勢

如果你想要一個「看得到、對得到」的精確方案,DECIMAL 是資料庫原生支援的定點數,也是業界最標準的做法。

DECIMAL 就像是會計師手中的精緻帳本,它會精確地把整數和小數分開儲存,確保 0.1 + 0.2 絕對等於 0.3

業界黃金比例:DECIMAL(19, 4)

通常我們會建議使用 DECIMAL(19, 4)

  • 19:代表總共可以存 19 位數字(精度)。
  • 4:代表小數點後保留 4 位。

為什麼要留 4 位小數?因為在計算利息、稅率或匯率時,中間過程往往會產生超過 2 位的小數位,多留 2 位緩衝區可以增加運算的精確度,最後再依照業務需求四捨五入即可。

這樣的容量,甚至足以讓你買下好幾個地球的 GDP 總和!

實際金融場景夠不夠用?

DECIMAL(19, 4) 為例:

  • 整數位:15 位
  • 最大金額:999,999,999,999,999
  • 美元換算:約 999 兆美元
參考值 金額
美國 GDP 約 27 兆美元
全球 GDP 總和 約 105 兆美元
全球財富總和 約 454 兆美元

DECIMAL(19, 4) 已經可以容納遠超全球財富總和的數字,對絕大多數金融系統來說完全足夠。

各大資料庫支援的最大 DECIMAL 的精度上限

資料庫 最大 precision
MySQL / MariaDB 65
PostgreSQL 131072(整數位)+ 16383(小數位)
SQL Server 38
Oracle 38

遊樂場的代幣機器:BIGINT 最小單位法

如果你正在追求極致的效能,或是像 Stripe、支付寶這種具備超高併發需求的系統,那麼 BIGINT(整數儲存法) 可能是你的首選。

這種做法就像是遊樂場的代幣機:不管你投入多少錢,機器都會把它換算成「最小單位」來儲存。例如:

  • 100.50 美元 → 儲存為 10050(美分)
  • 100 台幣 → 儲存為 100(元)

為什麼選 BIGINT?

原因 說明
速度極快 整數加減是 CPU 的拿手好戲,運算效能通常比 DECIMAL 快上許多。
空間效率 固定佔用 8 bytes,非常適合超大型資料庫。

不過,缺點是可讀性較差,你打開資料庫看到 10050 時,必須在腦袋(或程式碼)裡自動除以 100。

終極對決:該怎麼選?

要決定用哪一個,我們可以從 「查詢頻率」「系統規模」 來考量:

比較維度 DECIMAL BIGINT
可讀性 極佳(直接看數字) 較差(需手動換算)
運算速度 普通 極快
適用場景 ERP、內部財務系統、一般電商 高頻交易、超大型微服務、Stripe 風格 API

務實建議

適用場景 建議欄位
一般電商、公司內部報表系統,且會計人員需要直接下 SQL 來查帳 DECIMAL(19, 4)
高頻交易系統、或需要極致擴充性 BIGINT

總結

簡單來說,不管你選哪一種,千萬、絕對、永久禁止使用 FLOAT 存錢! 選擇正確的欄位類型,才能讓你的系統在金錢運算上穩如泰山。

All rights reserved,未經允許不得隨意轉載
使用 Hugo 建立
主題 StackJimmy 設計