在Insert overwrite到一張分區表時,可以在語句中指定分區的值。也可以用另外一種更加靈活的方式,在分區中指定一個分區列名,但不給出值。相應地,在select子句中的對應列來提供分區的值。

命令格式如下
insert overwrite table tablename partition (partcol1, partcol2 ...) select_statement from from_statement;
说明
  • select_statement欄位中,後面的欄位將提供目標表動態分區值。如目標表就一級動態分區,則select_statement最後一個欄位值即為目標表的動態分區值。
  • 目前,在使用動態資料分割函數的SQL中,在分布式環境下,單個進程最多隻能輸出512個動態分區,否則引發運行時異常。
  • 現階段,任意動態分區SQL不允許產生超過2000個動態分區,否則引發運行時異常。
  • 動態產生的分區值不允許為NULL,也不支援含特殊字元和中文,否則會引發異常。
    FAILED: ODPS-0123031:Partition exception - invalid dynamic partition value:
    province=xxx
  • 如果目標表有多級分區,在運行Insert語句時允許指定部分分區為靜態,但是靜態分區必須是進階分區。
動態分區的樣本如下
create table total_revenues (revenue bigint) partitioned by (region string);
insert overwrite table total_revenues partition(region)
select total_price as revenue, region
from sale_detail;

按照上述寫法,在SQL運行之前,是不知道會產生哪些分區的,只有在select運行結束後,才能由region欄位產生的值確定會產生哪些分區,這也是叫做動態分區的原因。

其他樣本如下
create table sale_detail_dypart like sale_detail;--建立樣本目標表
樣本一:
insert overwrite table sale_detail_dypart partition (sale_date, region)
select shop_name,customer_id,total_price,sale_date,region from sale_detail;
-- 成功返回;
  • 此時sale_detail表中,sale_date的值決定目標表的sale_date分區值,region的值決定目標表的region分區值。
  • 動態分區中,select_statement欄位和目標表動態分區的對應是按欄位順序決定的。如該樣本中,select語句若寫成select shop_name,customer_id,total_price,region,sale_date from sale_detail;,則sale_detail表中,region值決定決定目標表的 sale_date分區值,sale_date的值決定目標表的region分區值。
樣本二:
insert overwrite table sale_detail_dypart partition (sale_date='2013', region)
select shop_name,customer_id,total_price,region from sale_detail;
-- 成功返回,多級分區,指定一級分區
樣本三:
insert overwrite table sale_detail_dypart partition (sale_date='2013', region)
select shop_name,customer_id,total_price from sale_detail;
-- 失敗返回,動態分區插入時,動態分區列必須在select列表中
樣本四:
insert overwrite table sales partition (region='china', sale_date)
select shop_name,customer_id,total_price,sale_date from sale_detail;
-- 失敗返回,不能僅指定低級子分區,而動態插入進階分區
另外,舊版MaxCompute在進行動態分區時,如果分區列的類型與對應select列表中列的類型不嚴格一致,會報錯。MaxCompute2.0則支援隱式類型轉換,樣本如下:
create table parttable(a int, b double) partitioned by (p string);
insert into parttable partition(p) select key, value, current_timestmap() from src;
select * from parttable;
執行上述語句後返回結果如下:
a b c
0 NULL 2017-01-23 22:30:47.130406621
0 NULL 2017-01-23 22:30:47.130406621