DECIMAL数据类型

更新时间:
复制为 MD 格式

本文介绍MaxCompute DECIMAL数据类型的概念、注意事项、使用场景和使用示例。

概述

DECIMAL 是一种用于高精度十进制数值计算的数据类型,广泛应用于金融、科学计算等对精度要求严格的场景。在MaxCompute中,根据项目所采用的数据类型版本不同,DECIMAL 类型的行为存在差异:

  • 关闭DECIMAL 2.0数据类型

    DECIMAL 类型采用固定精度格式,默认为DECIMAL(54,18),precision(最多可以表示多少位的数字)和scale(小数部分位数)值不支持指定。整型部分取值范围:-1036+1~1036-1,小数部分精确到10-18。若使用此数据类型,需设置如下flag:

    SET odps.sql.decimal.odps2=false;
  • 开启DECIMAL 2.0数据类型

    默认为DECIMAL(38,18),用户可以设置其precision(最多可以表示多少位的数字)和scale(小数部分位数)值。根据精度需求分为以下两类:

    • 普通 DECIMAL:precision 范围为 [1,38],scale范围为 [0, precision]。若使用此数据类型,需设置如下flag:

      SET odps.sql.type.system.odps2=true;
      SET odps.sql.decimal.odps2=true;

      精度限制:

      • 若设置odps.sql.decimal2.extended.scale.enable=false(默认 false):

        支持 scale 范围为[0, 18],所有运算结果的小数位将被截断至 18 位。

      • 若设置odps.sql.decimal2.extended.scale.enable=true

        支持 scale 范围为[0, 38]的高精度计算。

      • 若设置odps.sql.decimal256.auto.promotion=true;开启自动类型提升:

        系统会根据需要将运算结果自动提升为更高精度的 DECIMAL256 类型,以支持更大范围的高精度计算。

    • DECIMAL256:precision 范围为 [39,76],scale范围为 [0, precision]。若使用此数据类型,需设置如下flag:

      SET odps.sql.type.system.odps2=true;
      SET odps.sql.decimal.odps2=true;
      SET odps.sql.decimal256.enable=true;
说明

启用odps.sql.decimal256.enable=true时,必须同时将odps.sql.type.system.odps2odps.sql.decimal.odps2设为true,否则查询将报错。

注意事项

  • 同一个表中不能同时存在新老DECIMAL数据类型。

  • DECIMAL 2.0数据类型下,执行SET odps.sql.hive.compatible=true;命令开启Hive兼容模式,或SET odps.sql.bigquery.compatible=true;命令开启BigQuery兼容模式时,DECIMAL(precision, scale)类型在数据导入(Tunnel Upload)和SQL运算过程中,如果数据的小数位数超过scale的大小,则会四舍五入。如果整数部分超出限制,系统不会报错,但输入数据会变为NULL值。

  • 当参数odps.sql.decimal.tostring.trimzero值为true时去掉小数点后末尾的零,为false时保留小数点后末尾的零。只对表里取数生效,对静态值不生效。默认值为true

使用场景

数据类型

典型配置

描述

旧版DECIMAL

SET odps.sql.decimal.odps2=false;

未开启DECIMAL 2.0数据类型,不支持指定precision/scale,默认为DECIMAL(54,18)

普通DECIMAL

SET odps.sql.decimal.odps2=true;
SET odps.sql.decimal2.extended.scale.enable=false;

普通DECIMAL类型,precision小于等于38,且在计算过程中,scale被限制不允许超过18。

SET odps.sql.decimal.odps2=true;
SET odps.sql.decimal2.extended.scale.enable=true;

普通DECIMAL类型,precision小于等于38,支持 scale 范围为[0, 38]的高精度计算。

DECIMAL256

SET odps.sql.type.system.odps2=true;

SET odps.sql.decimal.odps2=true;

SET odps.sql.decimal256.enable=true;

SET odps.sql.decimal2.extended.scale.enable=false;

SET odps.sql.decimal256.auto.promotion=false;

支持DECIMAL256类型,但在参与运算的DECIMALprecision小于等于38时,保持原有的行为不变。适合于从普通DECIMAL(scale范围为[0,18])类型升级到支持DECIMAL256类型的场景,可以保持原有的作业行为不变。

SET odps.sql.type.system.odps2=true;
SET odps.sql.decimal.odps2=true;
SET odps.sql.decimal256.enable=true;
SET odps.sql.decimal2.extended.scale.enable=true;
SET odps.sql.decimal256.auto.promotion=false;

支持DECIMAL256类型,但在参与运算的DECIMALprecision小于等于38时,保持原有的行为不变。适合于从普通DECIMAL(scale 范围为[0, 38])类型升级到支持DECIMAL256类型的场景,可以保持原有的作业行为不变。

SET odps.sql.type.system.odps2=true;
SET odps.sql.decimal.odps2=true;
SET odps.sql.decimal256.enable=true;
SET odps.sql.decimal2.extended.scale.enable=true;
SET odps.sql.decimal256.auto.promotion=true;

支持DECIMAL256类型,并且完全发挥了DECIMAL256的能力,适用于没有兼容性要求的全新project。

使用示例

关闭DECIMAL 2.0数据类型

示例1:DECIMAL类型默认为DECIMAL(54,18),不支持调整。

-- 关闭Decimal 2.0数据类型
SET odps.sql.decimal.odps2=false;

-- a是DECIMAL类型,取固定的precision/scale (54,18),不支持调整
CREATE OR REPLACE TABLE foo_t(a DECIMAL); 

-- 这个create语句会报错,因为在这种模式下不支持用户设置precision/scale
CREATE OR REPLACE TABLE foo_t(a DECIMAL(5,2));
-- 返回报错 FAILED: ODPS-0130071:[1,33] Semantic analysis exception - precision and scale is not currently supported in current mode, 'SET odps.sql.decimal.odps2=true' to enable

开启DECIMAL 2.0数据类型

  • 示例1:DECIMAL类型支持指定precision/scale。

    -- 开启DECIMAL 2.0数据类型
    SET odps.sql.decimal.odps2=true;
    
    CREATE OR REPLACE TABLE foo_t(a DECIMAL(4,2));
  • 示例2:若DECIMAL类型未指定precision/scale,其默认值取决于 Hive 兼容模式是否开启:关闭时默认为DECIMAL(38,18),开启时默认为DECIMAL(10,0)。

    -- 开启DECIMAL 2.0数据类型。,并关闭hive兼容模式
    SET odps.sql.decimal.odps2=true;
    SET odps.sql.hive.compatible=false;
    
    CREATE OR REPLACE TABLE foo_t(a DECIMAL);
    
    -- 显示a的数类型是DECIMAL(38,18)
    DESC foo_t;
    -- 返回结果
    +------------------------------------------------------------------------------------+
    | Owner:                    ALIYUN$odps_pd_testcloud_com                             |
    | Project:                  xxxx                                             |
    | TableComment:                                                                      |
    +------------------------------------------------------------------------------------+
    | CreateTime:               2026-04-21 13:36:21                                      |
    | LastDDLTime:              2026-04-21 13:36:21                                      |
    | LastModifiedTime:         2026-04-21 13:36:21                                      |
    +------------------------------------------------------------------------------------+
    | InternalTable: YES      | Size: 0                                                  |
    +------------------------------------------------------------------------------------+
    | Native Columns:                                                                    |
    +------------------------------------------------------------------------------------+
    | Field           | Type       | Label | Comment                                     |
    +------------------------------------------------------------------------------------+
    | a               | decimal(38,18) |       |                                             |
    +------------------------------------------------------------------------------------+
    
    -- 开启DECIMAL 2.0数据类型,并开启hive兼容模式
    SET odps.sql.decimal.odps2=true;
    SET odps.sql.hive.compatible=true;
    
    CREATE OR REPLACE TABLE foo_t(a DECIMAL);
    
    -- 显示a的数类型是DECIMAL(10,0)
    DESC foo_t;
    -- 返回结果
    +------------------------------------------------------------------------------------+
    | Owner:                    ALIYUN$odps_pd_testcloud_com                             |
    | Project:                  ***_project                                             |
    | TableComment:                                                                      |
    +------------------------------------------------------------------------------------+
    | CreateTime:               2026-04-21 13:38:04                                      |
    | LastDDLTime:              2026-04-21 13:38:04                                      |
    | LastModifiedTime:         2026-04-21 13:38:04                                      |
    +------------------------------------------------------------------------------------+
    | InternalTable: YES      | Size: 0                                                  |
    +------------------------------------------------------------------------------------+
    | Native Columns:                                                                    |
    +------------------------------------------------------------------------------------+
    | Field           | Type       | Label | Comment                                     |
    +------------------------------------------------------------------------------------+
    | a               | decimal(10,0) |       |                                             |
    +------------------------------------------------------------------------------------+
  • 示例3:对于普通 DECIMAL,precision 范围为 [1,38],scale范围为 [0, precision]。若需实现scale范围为[0,38]高精度计算,需设置SET odps.sql.decimal2.extended.scale.enable=true;

    SET odps.sql.type.system.odps2=true;
    SET odps.sql.decimal.odps2=true;  -- 开启Decimal 2.0数据类型
    SET odps.sql.decimal2.extended.scale.enable=true; -- 开启后,可实现scale范围为[0,38]高精度计算
    
    -- 2decimal相乘,所得结果的数据类型是decimal(22,19)
    EXPLAIN SELECT CAST(1bd AS DECIMAL(10,9))*CAST(1bd AS DECIMAL(11,10));
    -- 返回结果
    job0 is root job
    
    In Job job0:
    root Tasks: M1
    
    In Task M1:
        VALUES: _c0 : {1}
            Statistics: Num rows: 1.0, Data size: 16.0
            FS: output: Screen
                schema:
                  _c0 (decimal(22,19))
    
                Statistics: Num rows: 1.0, Data size: 16.0
                
    -- 将flag设置为false,输出类型的scale被截断到18,变成了decimal(22,18)
    SET odps.sql.decimal2.extended.scale.enable=false; -- 关闭后,scale范围为 [0,18]
    EXPLAIN SELECT CAST(1bd AS DECIMAL(10,9))*CAST(1bd AS DECIMAL(11,10));
    -- 返回结果
    job0 is root job
    
    In Job job0:
    root Tasks: M1
    
    In Task M1:
        VALUES: _c0 : {1}
            Statistics: Num rows: 1.0, Data size: 16.0
            FS: output: Screen
                schema:
                  _c0 (decimal(22,18))
    
                Statistics: Num rows: 1.0, Data size: 16.0
  • 示例4:对于DECIMAL256,precision 范围为 [39,76]。scale范围为 [0, precision]。

    SET odps.sql.type.system.odps2=true;
    SET odps.sql.decimal.odps2=true;
    SET odps.sql.decimal256.enable=true;
    
    CREATE OR REPLACE TABLE foo_t(a decimal(60,10));
    
    EXPLAIN SELECT * FROM foo_t;
    -- 返回结果
    job0 is root job
    
    In Job job0:
    root Tasks: M1
    
    In Task M1:
        Data source: ***_project.foo_t
        TS: muze_project.foo_t
            Statistics: Num rows: 1.0, Data size: 16.0
            FS: output: Screen
                schema:
                  a (decimal(60,10))
    
                Statistics: Num rows: 1.0, Data size: 16.0
    
  • 示例5:两个普通DECIMAL进行运算,默认情况下,所得的结果是普通DECIMAL类型,若超出范围会对数据进行截断。

    SET odps.sql.type.system.odps2=true;
    SET odps.sql.decimal.odps2=true;
    
    -- 结果类型为 decimal(38,5),因超出普通 DECIMAL 范围而被截断
    EXPLAIN SELECT CAST(1bd AS DECIMAL(30,5)) * CAST(1bd AS DECIMAL(30,0));
    -- 返回结果
    job0 is root job
    
    In Job job0:
    root Tasks: M1
    
    In Task M1:
        VALUES: _c0 : {1}
            Statistics: Num rows: 1.0, Data size: 16.0
            FS: output: Screen
                schema:
                  _c0 (decimal(38,5))
    
                Statistics: Num rows: 1.0, Data size: 16.0
    

    而当启用 DECIMAL256 并设置SET odps.sql.decimal256.auto.promotion=true;开启自动类型提升后,系统会将运算结果自动提升至 DECIMAL256 支持的更高精度类型,从而避免截断,保留完整精度。

    SET odps.sql.type.system.odps2=true;
    SET odps.sql.decimal.odps2=true;
    SET odps.sql.decimal256.enable=true;
    SET odps.sql.decimal256.auto.promotion=true;
    
    -- 结果类型是decimal(61,5),两个普通decimal相乘的结果被promotedecimal256的范围中
    EXPLAIN SELECT CAST(1bd AS DECIMAL(30,5)) * CAST(1bd AS DECIMAL(30,0));
    -- 返回结果
    job0 is root job
    
    In Job job0:
    root Tasks: M1
    
    In Task M1:
        VALUES: _c0 : {1}
            Statistics: Num rows: 1.0, Data size: 16.0
            FS: output: Screen
                schema:
                  _c0 (decimal(61,5))
    
                Statistics: Num rows: 1.0, Data size: 16.0