杂记:postgresql 除法的坑_tiger_zhao的博客-爱代码爱编程
还是 Oracle 转 PostgreSQl 的坑
整数除
假设有 Decimal(12,2) 金额=1234, int 费率=5
(表示5%)
要计算 费率=金额*费率/100
,那么 Oracle 下面的表达式都没问题
with T as (
select CAST(1234 AS DECIMAL(12,2)) A, CAST(5 AS int) R from DUAL
)
select round(A * R / 100, 2) expr1, round(A * (R / 100), 2) expr2 from T
返回
expr1 | expr2 |
---|---|
61.7 | 61.7 |
然后对应到 PostgreSQL 中
with T as (
select 1234 ::numeric(12,2) A, 5 ::int R
)
select round(A * R / 100, 2) expr1, round(A * (R / 100), 2) expr2 from T
返回
expr1 | expr2 |
---|---|
61.7 | 0.00 |
瞧,expr2 变成了零,因为在 PostgreSQL 中 5 / 100 = 0
没有小数!
谁TMD整除会比普通除还常用,设计 PostgreSQL 语法的人脑子有病!
小数除
无论是 Oracle 自动转类型还是 PostgreSQL 强制转类型保证运算正确,计算中间最常见中间类型是 Decimal/Numeric
。
在 Oracle 中模拟一下
with T as (
select cast(1234 as numeric) A, cast(10 as numeric) R from DUAL
)
select R / 100 expr1, A * (R / 100) expr2 from T
返回
expr1 | expr2 |
---|---|
0.1 | 123.4 |
然后对应到 PostgreSQL 中
with T as (
select 1234 ::numeric A, 10 ::numeric R
)
select R / 100 expr1, A * (R / 100) expr2 from T
返回
expr1 | expr2 |
---|---|
0.10000000000000000000 | 123.40000000000000000000 |
瞧,小数除法可能会多出好多无用0,并且会随加减乘等运算蔓延。通过 JDBC 字段类型对应到 BigDecimal,也会保留尾部的无用0进行显示;用 round()
只能固定小数位、和原样一致要用 trim_scale
select trim_scale(R / 100) expr1, trim_scale(A * (R / 100)) expr2 from T
返回
expr1 | expr2 |
---|---|
0.1 | 123.4 |