DECIMAL資料類型

更新時間:
Copy as 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