DECIMAL

DECIMAL
DECIMAL
类型用于表示具有特定最大精度和固定小数位数的数值。这种数据类型在处理金融、会计或其他需要精确数值计算的场景中非常有用,因为它可以避免浮点数运算的舍入误差。

语法

DECIMAL(precision, scale)

  • precision
    precision
    :表示数字的总位数,包括小数点两侧的位数。取值范围为1到38。
  • scale
    scale
    :表示小数点后的位数。取值范围为0到
    precision
    precision
    ,且不能大于
    precision
    precision

字面量

DECIMAL 类型的字面量可以使用

BD
BD
后缀来表示:

SELECT 3.14BD; -- DECIMAL 类型的 3.14 SELECT 1234BD; -- DECIMAL 类型的 1234

不带后缀的小数字面量(如

3.14
3.14
)默认也会被解析为 DECIMAL 类型。

示例

SELECT CAST(1234.56 AS DECIMAL(10, 2)); -- 结果为 1234.56 SELECT CAST(123.456 AS DECIMAL(5, 3)); -- 结果为 null SELECT CAST(1.23 AS DECIMAL(4, 2)); -- 结果为 1.23 SELECT CAST(1234 AS DECIMAL(6, 2)); -- 结果为 1234.00 SELECT CAST(0.1234 AS DECIMAL(5, 4)); -- 结果为 0.1234

算术运算结果类型

对两个

DECIMAL
DECIMAL
类型的值进行算术运算时,结果的
precision
precision
scale
scale
按以下规则计算。

设两个操作数类型为

DECIMAL(p1, s1)
DECIMAL(p1, s1)
DECIMAL(p2, s2)
DECIMAL(p2, s2)

加法与减法

result_precision = max(s1, s2) + max(p1 - s1, p2 - s2) + 1 result_scale = max(s1, s2)

示例

DECIMAL(10, 2) + DECIMAL(8, 4)
DECIMAL(10, 2) + DECIMAL(8, 4)
DECIMAL(13, 4)
DECIMAL(13, 4)

  • scale = max(2, 4) = 4
  • precision = 4 + max(10-2, 8-4) + 1 = 4 + 8 + 1 = 13

乘法

result_precision = p1 + p2 + 1 result_scale = s1 + s2

示例

DECIMAL(10, 2) * DECIMAL(8, 3)
DECIMAL(10, 2) * DECIMAL(8, 3)
DECIMAL(19, 5)
DECIMAL(19, 5)

  • precision = 10 + 8 + 1 = 19
  • scale = 2 + 3 = 5

除法

result_precision = p1 - s1 + s2 + max(6, s1 + p2 + 1) result_scale = max(6, s1 + p2 + 1)

示例

DECIMAL(10, 2) / DECIMAL(8, 3)
DECIMAL(10, 2) / DECIMAL(8, 3)
DECIMAL(19, 11)
DECIMAL(19, 11)

  • scale = max(6, 2 + 8 + 1) = 11
  • precision = (10 - 2) + 3 + 11 = 22

取模 (%)

result_precision = min(p1 - s1, p2 - s2) + max(s1, s2) result_scale = max(s1, s2)

示例

DECIMAL(10, 2) % DECIMAL(8, 3)
DECIMAL(10, 2) % DECIMAL(8, 3)
DECIMAL(8, 3)
DECIMAL(8, 3)

  • scale = max(2, 3) = 3
  • precision = min(10-2, 8-3) + 3 = 5 + 3 = 8

聚合函数

函数结果 precision结果 scale
SUMp + 10s
AVGp + 4s + 4

Precision 超过 38 时的调整

DECIMAL 的最大 precision 为 38。当上述公式计算出的 precision 超过 38 时,系统会进行如下调整:

intDigits = precision - scale adjustedScale = max(min(scale, 6), 38 - intDigits) 最终结果 = DECIMAL(38, adjustedScale)

调整逻辑的核心思路:

  • 优先保证整数部分不丢失(整数位 = 38 - adjustedScale)
  • 小数位至少保留
    min(scale, 6)
    min(scale, 6)
    位(即最少 6 位,除非原始 scale 本身小于 6)
  • 如果整数位已经占满 38 位,则 adjustedScale 退化为
    min(scale, 6)
    min(scale, 6)

示例

DECIMAL(38, 7) + DECIMAL(10, 0)
DECIMAL(38, 7) + DECIMAL(10, 0)
的理论结果为
DECIMAL(39, 7)
DECIMAL(39, 7)
,超过 38 后调整为:

  • intDigits = 39 - 7 = 32
  • adjustedScale = max(min(7, 6), 38 - 32) = max(6, 6) = 6
  • 最终结果:
    DECIMAL(38, 6)
    DECIMAL(38, 6)

与整数运算

当 DECIMAL 与整数类型进行运算时,整数会先被转换为对应的 DECIMAL 类型,再按上述规则计算:

整数类型转换后的 DECIMAL
TINYINTDECIMAL(3, 0)
SMALLINTDECIMAL(5, 0)
INTDECIMAL(10, 0)
BIGINTDECIMAL(20, 0)

如果整数是字面量常量,系统会根据实际值推断更精确的类型(例如常量

5
5
会被推断为
DECIMAL(1, 0)
DECIMAL(1, 0)
而非
DECIMAL(10, 0)
DECIMAL(10, 0)
)。

与浮点数运算

当 DECIMAL 与 FLOAT/DOUBLE 进行运算时,结果类型为 DOUBLE。

使用指南

  • scale
    scale
    为0时,表示数值为整数。
  • precision
    precision
    scale
    scale
    的值相同时,表示数值为纯小数(即所有位数都在小数点后)。
  • 在进行数值转换时,如果转换结果超出了
    DECIMAL
    DECIMAL
    类型的范围,可能会发生数据截断或舍入。
  • 在比较
    DECIMAL
    DECIMAL
    类型的数值时,应考虑其精度和尺度,以避免因舍入误差导致的比较错误。
  • 在多步运算中,precision 可能逐步增长直至触发调整。建议在关键计算节点使用
    CAST
    CAST
    显式控制精度,避免意外的精度损失。

注意事项

  • 在使用
    DECIMAL
    DECIMAL
    类型时,应根据实际需求合理选择
    precision
    precision
    scale
    scale
    的值,以确保数值的精确性和计算的准确性。
  • 除法运算的 scale 至少为 6,即使两个操作数的 scale 都为 0,除法结果也会保留 6 位小数。
  • 当 precision 超过 38 触发调整时,小数部分可能被截断,导致精度损失。如果业务对小数精度敏感,应提前规划操作数的 precision 和 scale,避免触发调整。

联系我们
预约咨询
微信咨询
电话咨询