DECIMAL
DECIMAL类型用于表示具有特定最大精度和固定小数位数的数值。这种数据类型在处理金融、会计或其他需要精确数值计算的场景中非常有用,因为它可以避免浮点数运算的舍入误差。
语法
:表示数字的总位数,包括小数点两侧的位数。取值范围为1到38。precision
:表示小数点后的位数。取值范围为0到scale
,且不能大于precision
。precision
字面量
DECIMAL 类型的字面量可以使用
BD 后缀来表示:
不带后缀的小数字面量(如
3.14)默认也会被解析为 DECIMAL 类型。
示例
算术运算结果类型
对两个
DECIMAL 类型的值进行算术运算时,结果的 precision 和 scale 按以下规则计算。
设两个操作数类型为
DECIMAL(p1, s1) 和 DECIMAL(p2, s2):
加法与减法
示例:
DECIMAL(10, 2) + DECIMAL(8, 4) → DECIMAL(13, 4)
- scale = max(2, 4) = 4
- precision = 4 + max(10-2, 8-4) + 1 = 4 + 8 + 1 = 13
乘法
示例:
DECIMAL(10, 2) * DECIMAL(8, 3) → DECIMAL(19, 5)
- precision = 10 + 8 + 1 = 19
- scale = 2 + 3 = 5
除法
示例:
DECIMAL(10, 2) / DECIMAL(8, 3) → DECIMAL(19, 11)
- scale = max(6, 2 + 8 + 1) = 11
- precision = (10 - 2) + 3 + 11 = 22
取模 (%)
示例:
DECIMAL(10, 2) % DECIMAL(8, 3) → DECIMAL(8, 3)
- scale = max(2, 3) = 3
- precision = min(10-2, 8-3) + 3 = 5 + 3 = 8
聚合函数
| 函数 | 结果 precision | 结果 scale |
|---|---|---|
| SUM | p + 10 | s |
| AVG | p + 4 | s + 4 |
Precision 超过 38 时的调整
DECIMAL 的最大 precision 为 38。当上述公式计算出的 precision 超过 38 时,系统会进行如下调整:
调整逻辑的核心思路:
- 优先保证整数部分不丢失(整数位 = 38 - adjustedScale)
- 小数位至少保留
位(即最少 6 位,除非原始 scale 本身小于 6)min(scale, 6) - 如果整数位已经占满 38 位,则 adjustedScale 退化为
min(scale, 6)
示例:
DECIMAL(38, 7) + DECIMAL(10, 0) 的理论结果为 DECIMAL(39, 7),超过 38 后调整为:
- intDigits = 39 - 7 = 32
- adjustedScale = max(min(7, 6), 38 - 32) = max(6, 6) = 6
- 最终结果:
DECIMAL(38, 6)
与整数运算
当 DECIMAL 与整数类型进行运算时,整数会先被转换为对应的 DECIMAL 类型,再按上述规则计算:
| 整数类型 | 转换后的 DECIMAL |
|---|---|
| TINYINT | DECIMAL(3, 0) |
| SMALLINT | DECIMAL(5, 0) |
| INT | DECIMAL(10, 0) |
| BIGINT | DECIMAL(20, 0) |
如果整数是字面量常量,系统会根据实际值推断更精确的类型(例如常量
5 会被推断为 DECIMAL(1, 0) 而非 DECIMAL(10, 0))。
与浮点数运算
当 DECIMAL 与 FLOAT/DOUBLE 进行运算时,结果类型为 DOUBLE。
使用指南
- 当
为0时,表示数值为整数。scale - 当
和precision
的值相同时,表示数值为纯小数(即所有位数都在小数点后)。scale - 在进行数值转换时,如果转换结果超出了
类型的范围,可能会发生数据截断或舍入。DECIMAL - 在比较
类型的数值时,应考虑其精度和尺度,以避免因舍入误差导致的比较错误。DECIMAL - 在多步运算中,precision 可能逐步增长直至触发调整。建议在关键计算节点使用
显式控制精度,避免意外的精度损失。CAST
注意事项
- 在使用
类型时,应根据实际需求合理选择DECIMAL
和precision
的值,以确保数值的精确性和计算的准确性。scale - 除法运算的 scale 至少为 6,即使两个操作数的 scale 都为 0,除法结果也会保留 6 位小数。
- 当 precision 超过 38 触发调整时,小数部分可能被截断,导致精度损失。如果业务对小数精度敏感,应提前规划操作数的 precision 和 scale,避免触发调整。
联系我们
