注册
CALC_AS_DECIMAL算术运算参数详解
技术分享/ 文章详情 /

CALC_AS_DECIMAL算术运算参数详解

阿白 2025/05/16 47 1 0

1 应用场景

达梦数据库中的CALC_AS_DECIMAL参数用于控制某些特定算术运算(特别是整数之间的除法,以及整数与可转换为数字的字符串/二进制数据进行的运算)的结果数据类型。它主要解决了用户在这些场景下可能遇到的计算结果与预期不符的问题,例如期望得到带小数的除法结果,但数据库默认却返回了整数。通过设置此参数,用户可以选择让这些运算强制产生具有小数精度的结果类型(如DECIMAL),以确保计算的准确性。如果此参数的设置与业务对计算结果所需精度的要求不符,就可能导致计算结果偏离预期,比如丢失重要的小数部分,从而影响基于这些计算结果的后续业务处理或数据分析的正确性。

2 参数简介

2.1 CALC_AS_DECIMAL

CALC_AS_DECIMAL 参数 (静态参数)

描述
0 默认值,表示整数类型的除法、整数与字符或 BINARY 串的所有四则运算,结果都处理成整数;
1 表示整数类型的除法全部转换为 DEC(0,0) 处理;
2 表示将整数与字符或 BINARY 串的所有四则运算都转换为 DEC(0,0) 处理;
3 所有涉及整型的四则运算全部转换为 DEC(0,0) 处理;

简单来说,假设你有两个整数,10和3,计算10/3:

  • 如果CALC_AS_DECIMAL设置得让结果保持整数,你可能得到3(小数部分被丢掉了)。
  • 如果CALC_AS_DECIMAL设置得让结果保留小数,你可能得到 3.333…。

同样,如果你用一个整数比如10去加一个字符串 ‘5’:

  • 数据库会先试着把’5’转成数字5。
  • 然后计算10+5。
  • 这个结果是15。但这个结果的数据类型是INT类型还是DECIMAL类型,也受CALC_AS_DECIMAL参数的影响。

2.2 USE_PLN_POOL

该参数的有效性受到USE_PLN_POOL参数的影响。当USE_PLN_POOL的值为0或1时,CALC_AS_DECIMAL有效。当USE_PLN_POOL为2或3时,CALC_AS_DECIMAL的行为将按照其取值为2的情况处理。

USE_PLN_POOL 参数 (是否重用执行计划, 静态参数)

描述
0 禁用执行计划的重用。每条SQL语句在每次执行时都会生成一个新的执行计划。
1 启用基本的执行计划重用功能。数据库会为已执行过的、完全相同的SQL文本尝试重用已缓存的执行计划。这是默认设置。
2 启用执行计划重用,并对不包含显式绑定参数的语句进行常量参数化优化。例如,像SELECT * FROM T WHERE C=10SELECT * FROM T WHERE C=20这样的查询,如果它们结构相同只是常量值不同,数据库可能会将常量值进行参数化处理,生成一个参数化的计划(如SELECT * FROM T WHERE C=?),提高计划的重用率。简单来说,只对那些直接写死常量值的简单情况进行参数化。
3 启用执行计划重用,采取更积极的常量参数化策略。即使对于包含显式绑定参数的语句,或者结构上看起来不太容易参数化的语句,系统也可能会尝试进行常量参数化优化,进一步提高计划重用率。简单来说,在处理设置2的基础上会分析更多可参数化的点。

2.3 什么是DEC(P, S)

DEC是DECIMAL数据类型的缩写。例如dec(3,1)指的就是这整个数字只有3位,但小数点后只有1位,例如12.5、65.2这些数字。而CALC_AS_DECIMAL参数中DEC(0,0)并不是说它的刻度和精度都是0,而是启用DECIMAL的高精度运算模式。最终的刻度和精度是根据运算的数值和规则动态确定的,而不是固定为DEC(0,0)。

  • P表示精度,即总的数字位数(包括小数点前和小数点后)。
  • S表示刻度,即小数点后的位数。

3 CALC_AS_DECIMAL不同取值的效果分析

3.1 创建测试表及插入测试数据

-- 创建测试表 CREATE TABLE comprehensive_test ( C1 INT, -- 整数列 C2 INT, -- 另一个整数列,用于纯整数运算 C3 VARCHAR(10), -- 字符型数字列 (可转换为整数或小数) C4 BINARY(4) -- BINARY 列 (表示整数) ); -- 插入测试数据 INSERT INTO comprehensive_test (C1, C2, C3, C4) VALUES (10, 3, '5', 0x00000002); INSERT INTO comprehensive_test (C1, C2, C3, C4) VALUES (7, 2, '3', 0x00000003); INSERT INTO comprehensive_test (C1, C2, C3, C4) VALUES (8, 4, '2.5', 0x00000004); INSERT INTO comprehensive_test (C1, C2, C3, C4) VALUES (9, 3, '3.0', 0x00000002); COMMIT; -- 查看插入的数据 SELECT * FROM comprehensive_test;

3.2 执行查询语句

--纯整数计算 SELECT C1, C2, C1 / C2 AS 整数_除以_整数, C1 + C2 AS 整数_加_整数, C1 - C2 AS 整数_减_整数, C1 * C2 AS 整数_乘以_整数 FROM comprehensive_test; --整数与字符计算 SELECT C1, C3, C1 / C3 AS 整数_除以_字符, C1 + C3 AS 整数_加_字符, C1 - C3 AS 整数_减_字符, C1 * C3 AS 整数_乘以_字符 FROM comprehensive_test; --整数与 BINARY计算 SELECT C1, C4, C1 / C4 AS 整数_除以_二进制, C1 + C4 AS 整数_加_二进制, C1 - C4 AS 整数_减_二进制, C1 * C4 AS 整数_乘以_二进制 FROM comprehensive_test;

3.3 调整语句参数

sp_set_para_value(2,'CALC_AS_DECIMAL',0); --重启数据库后检查 select PARA_NAME,PARA_VALUE from v$dm_ini where para_name LIKE 'CALC_AS_DECIMAL';

3.4 CALC_AS_DECIMAL = 0

表示整数类型的除法、整数与字符或 BINARY 串的所有四则运算,结果都处理成整数。
image.png
image.png
image.png

  1. 纯整数运算
    • 计算结果:除法会截断小数点,加减乘是整数计算。
    • 结果类型:全部是INTEGER。
  2. 整数与字符型数字运算
    • 计算结果:无论是除法还是加减乘,如果计算结果本身有小数(例如7/‘3’=2.333…, 8+‘2.5’=10.5),数值会保留小数点;如果计算结果是整数(例如10/‘5’=2, 8+‘2.0’=10),数值就显示为整数。
    • 结果类型:全部是DECIMAL(38, 0)。
  3. 整数与BINARY运算
    • 计算结果:除法会截断小数点(例如7/3=2.33->2, 9/2=4.5->4),加减乘是整数计算。
    • 结果类型:全部是INTEGER。

3.5 CALC_AS_DECIMAL = 1

表示整数类型的除法全部转换为DEC(0,0)处理。
image.png
image.png
image.png

  1. 纯整数运算
    • 计算结果:除法会保留小数点,加减乘是整数计算。
    • 结果类型:除法是DECIMAL(38, 0),加减乘是INTEGER。
    • 与CALC_AS_DECIMAL= 0对比:除法从INTEGER截断变为DECIMAL保留小数点。
  2. 整数与字符型数字运算
    • 计算结果:与CALC_AS_DECIMAL= 0时相同。计算结果是整数时显示为整数,计算结果有小数时保留小数点显示。
    • 结果类型:与CALC_AS_DECIMAL= 0时相同。全部是DECIMAL(38, 0)。
    • 与CALC_AS_DECIMAL= 0对比:无变化。
  3. 整数与BINARY运算
    • 计算结果:除法会保留小数点,加减乘是整数计算。
    • 结果类型:除法是DECIMAL(38, 0),加减乘是INTEGER。
    • 与CALC_AS_DECIMAL= 0对比:除法从INTEGER截断变为DECIMAL保留小数点。

总结:相对于CALC_AS_DECIMAL= 0,参数1改变了除法运算的行为,无论是纯整数除法还是整数与BINARY的除法,结果都从INTEGER截断变为了DECIMAL保留小数点。而整数与字符型数字的运算,以及纯整数或BINARY加减乘运算,与参数0保持一致。

3.6 CALC_AS_DECIMAL = 2

表示将整数与字符或BINARY串的所有四则运算都转换为DEC(0,0)处理。
image.png
image.png
image.png

  1. 纯整数运算
    • 计算结果:除法会保留小数点,加减乘是整数计算。
    • 结果类型:除法是DECIMAL(38, 0),加减乘是INTEGER。
    • 与CALC_AS_DECIMAL= 1对比:无变化。
  2. 整数与字符型数字运算
    • 计算结果:与CALC_AS_DECIMAL= 1时相同。计算结果是整数时显示为整数,计算结果有小数时保留小数点显示。
    • 结果类型:与CALC_AS_DECIMAL= 1时相同。全部是DECIMAL(38, 0)。
    • 与CALC_AS_DECIMAL= 1对比:无变化。
  3. 整数与BINARY运算
    • 计算结果:除法会保留小数点,加减乘是整数计算。
    • 结果类型:全部是DECIMAL(38, 0)。
    • 与CALC_AS_DECIMAL= 1对比:除法类型相同,但加减乘类型从INTEGER变为DECIMAL(38,0)。

总结:相对于CALC_AS_DECIMAL= 1,参数2在整数与BINARY的加减乘运算上存在差异:结果类型从INTEGER变为了DECIMAL(38,0)。其他运算类型(纯整数运算、整数与字符运算、整数与BINARY除法)的结果类型和计算结果与参数1保持一致。

3.7 CALC_AS_DECIMAL = 3

所有涉及整型的四则运算全部转换为DEC(0,0)处理。
image.png
image.png
image.png

  1. 纯整数运算
    • 计算结果:除法保留小数点;加减乘是整数计算。数值显示取决于计算结果本身是否是整数;若计算结果小数位为0,则以整数形式展示;若计算结果小数位不为0,则以带小数形式展示。
    • 结果类型:全部是DECIMAL(38, 0)。
    • 与CALC_AS_DECIMAL= 2对比:加减乘的类型从INTEGER变为DECIMAL(38,0)。
  2. 整数与字符型数字运算
    • 计算结果:数值取决于计算结果本身是否是整数;若计算结果小数位为0,则以整数形式展示;若计算结果小数位不为0,则以带小数形式展示。
    • 结果类型:全部是DECIMAL(38, 0)。
    • 与CALC_AS_DECIMAL= 2对比:无变化。
  3. 整数与BINARY运算
    • 计算结果:数值取决于计算结果本身是否是整数;若计算结果小数位为0,则以整数形式展示;若计算结果小数位不为0,则以带小数形式展示。
    • 结果类型:全部是DECIMAL(38, 0)。
    • 与CALC_AS_DECIMAL= 2对比:无变化。

总结:当配置为3时,所有数值都遵循DECIMAL的规则。相较于CALC_AS_DECIMAL= 2,参数3的差异在于纯整数加减乘的结果类型从INTEGER变为DECIMAL(38,0),其他已为DECIMAL(38,0) 的运算类型保持不变。

4 不可转换数字字符串运算

数据库尝试将字符值’ABC’强制转换为数字类型以执行加法运算,但’ABC’ 不是一个有效的数字表示,因此转换失败导致计算终止报错。

--数据插入 INSERT INTO test_calc (c1, c2, c3, c4) VALUES (5, 2, 'TEST', 'ABC'); commit; --执行计算 SELECT c1 + c4 FROM test_calc WHERE c4 = 'ABC';

image.png

评论
后发表回复

作者

文章

阅读量

获赞

扫一扫
联系客服