DECIMAL資料類型
本文介紹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.odps2和odps.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 |
| 未開啟DECIMAL 2.0資料類型,不支援指定precision/scale,預設為 |
普通DECIMAL |
| 普通DECIMAL類型,precision小於等於38,且在計算過程中,scale被限制不允許超過18。 |
| 普通DECIMAL類型,precision小於等於38,支援 scale 範圍為 | |
DECIMAL256 |
| 支援DECIMAL256類型,但在參與運算的DECIMAL的precision小於等於38時,保持原有的行為不變。適合於從普通DECIMAL(scale範圍為 |
| 支援DECIMAL256類型,但在參與運算的DECIMAL的precision小於等於38時,保持原有的行為不變。適合於從普通DECIMAL(scale 範圍為 | |
| 支援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]高精度計算 -- 2個decimal相乘,所得結果的資料類型是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相乘的結果被promote到decimal256的範圍中 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