一、現象:ROUND 怎麼“不靈”了?
上週五,業務同學拿着一條 SQL 跑來:
SELECT ROUND(198/60, 2) AS val FROM dual;
結果赫然是:
VAL
---
3
他一臉懵:“我明明 ROUND 到 2 位小數,為什麼連小數點都沒看見?”
二、排查:ROUND 背鍋了嗎?
先把 ROUND 摘出來單獨跑:
SELECT ROUND(3.30, 2) FROM dual; -- 正常返回 3.30
ROUND 沒問題!
那問題只能出在 198/60 身上。
三、根因:整數除法先截斷
達夢(以及 Oracle、PG 等很多數據庫)遵循 整數/整數=整數 的規則:
SELECT 198/60 FROM dual; -- 先整除,得 3
此時 3 已經 沒有小數部分 了,再 ROUND(3, 2) 自然還是 3。
於是出現了“ROUND 失效”的假象。
四、復現:一句話驗證
|
SQL
|
結果
|
類型
|
|
|
3
|
整數
|
|
|
3.3
|
數值
|
|
|
3.3
|
數值
|
五、解決方案:讓除法變成浮點運算
- 把除數寫成小數
ROUND(198/60.0, 2) -- 3.30
- 或者顯式轉換
ROUND( CAST(198 AS NUMERIC(10,2))/60 , 2)
- 乘法技巧(兼容 MySQL 習慣)
ROUND(198*1.00/60, 2)
六、真實業務 SQL 改寫前後
改寫前(看似丟小數):
SELECT ROUND(SUM(cnt)/60, 2) AS val FROM t_report;
改寫後(小數正常):
SELECT ROUND(SUM(cnt)/60.0, 2) AS val FROM t_report;
七、踩坑小結
- ROUND 不背鍋,先查除法。
- 整數除法 = 隱式 TRUNC,數據庫一視同仁。
- 萬能套路:除數
*1.0或寫.0後綴,立即變浮點。 - 該規則同樣適用於 Oracle、PostgreSQL、SQL Server 等,達夢只是“繼承”了傳統。
八、一句話記憶
“整數相除先截斷,想留小數先變浮!”
九、參考文檔
- 達夢 SQL 語言參考 §數值運算類型轉換規則
- 《Oracle 隱式類型轉換》—— 同樣適用於達夢
如果本文幫到了你,歡迎點贊/收藏,把“小坑”分享給更多小夥伴!