一、現象: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

結果

類型

SELECT 198/60 FROM dual;

3

整數

SELECT 198/60.0 FROM dual;

3.3

數值

SELECT 198*1.00/60 FROM dual;

3.3

數值


五、解決方案:讓除法變成浮點運算

  1. 把除數寫成小數
ROUND(198/60.0, 2)   -- 3.30
  1. 或者顯式轉換
ROUND( CAST(198 AS NUMERIC(10,2))/60 , 2)
  1. 乘法技巧(兼容 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;

七、踩坑小結

  1. ROUND 不背鍋,先查除法。
  2. 整數除法 = 隱式 TRUNC,數據庫一視同仁。
  3. 萬能套路:除數 *1.0 或寫 .0 後綴,立即變浮點。
  4. 該規則同樣適用於 Oracle、PostgreSQL、SQL Server 等,達夢只是“繼承”了傳統。

八、一句話記憶

“整數相除先截斷,想留小數先變浮!”


九、參考文檔

  • 達夢 SQL 語言參考 §數值運算類型轉換規則
  • 《Oracle 隱式類型轉換》—— 同樣適用於達夢

如果本文幫到了你,歡迎點贊/收藏,把“小坑”分享給更多小夥伴!