DECIMAL 精度的定义与数据库上限

DECIMAL(p, s) 两个参数的含义

参数名称含义例:DECIMAL(38,10)
pPrecision(精度)数值的总位数(整数部分 + 小数部分)共 38 位
sScale(标度)小数点后保留的位数小数点后 10 位

核心公式

整数部分位数 = p − s

DECIMAL(38,10) → 整数部分 38 − 10 = 28 位

⚠️ 关键坑:p 有数据库上限

p 不是可以随意写大的,超出数据库上限会直接报”数据精度超出范围”:

数据库p 的上限
达梦(DM)38
Oracle38
MySQL65
SQL Server38
-- ❌ 达梦报错:p = 50 超出上限 38
CREATE TABLE t (amount DECIMAL(50, 5));
 
-- ✅ 改为 38,整数部分仍有 33 位,绝大多数 ERP 场景够用
CREATE TABLE t (amount DECIMAL(38, 5));

从其他数据库迁移到达梦时必查

MySQL 上能正常建表的 DECIMAL(50,5),迁到达梦会直接失败。这是数据库方言差异,不是数据问题。

常见定义与适用场景

定义整数部分小数部分典型用途
DECIMAL(10,2)8 位2 位金额(元/分)
DECIMAL(18,6)12 位6 位数量 / 单价
DECIMAL(38,5)33 位5 位大额汇总
DECIMAL(38,10)28 位10 位科学计算、高精度汇总
DECIMAL(38,0)38 位0 位纯整数
DECIMAL(10)10 位0 位等价于 DECIMAL(10,0)

写入时的两种行为

-- ① 小数部分超出 s → 四舍五入(不报错,静默改值)
--    DECIMAL(10,2) 插入 123.4567
INSERT INTO t VALUES (123.4567);
-- 实际存储: 123.46
 
-- ② 整数部分超出 p−s → 报错
--    DECIMAL(10,2) 只能存 8 位整数,插 100000000
-- 报错:数据精度超出范围

静默四舍五入是金额场景的隐患

场景①不报错、只悄悄改值。金额字段若用 DECIMAL(10,2) 承接更高精度的小数,误差会静默累积,务必在应用层明确舍入规则。

参考链接