全部產品
Search
文件中心

MaxCompute:UPDATE

更新時間:Dec 23, 2025

UPDATE操作用於將Transactional表或Delta Table表中行對應的單列或多列資料更新為新值。

前提條件

執行DELETEUPDATE操作前需要具備目標Transactional表或Delta Table表的讀取表資料許可權(Select)及更新表資料許可權(Update)。授權操作請參見MaxCompute許可權

使用限制

  • DELETEUPDATE功能及對應Transactional表、Delta Table表的使用限制如下:

    說明

    關於Transaction表和Delta Table表詳細資料,詳情請參見Transaction Table與Delta Table表參數

    • Delta Table表UPDATE文法不支援修改PK列。

注意事項

通過DELETEUPDATE操作刪除或更新表或分區內的資料時,注意事項如下:

  • 如果需要對錶中較少資料進行刪除或更新操作,且操作和後續讀資料的頻率也不頻繁,建議使用DELETEUPDATE操作,並且在多次執行刪除或更新操作之後,請合并表的Base檔案和Delta檔案,降低表的實際儲存。更多資訊,請參見合并Transactional表檔案

  • 如果刪除或更新行數較多(超過5%)並且操作不頻繁,但後續對該表的讀操作比較頻繁,建議使用INSERT OVERWRITEINSERT INTO操作。更多資訊,請參見插入或覆寫資料(INSERT INTO | INSERT OVERWRITE)

    例如,某業務情境為每次刪除或更新10%的資料,一天更新10次。建議根據實際情況評估DELETEUPDATE操作產生的費用及後續對讀效能的消耗是否小於每次使用INSERT OVERWRITEINSERT INTO操作產生的費用及後續對讀效能的消耗,比較兩種方式在具體情境中的效率,選擇更優方案。

  • 刪除資料會產生Delta檔案,所以刪除資料不一定能降低儲存,如果您希望通過DELETE操作刪除資料來降低儲存,請合并表的Base檔案和Delta檔案,降低表的實際儲存。更多資訊,請參見合并Transactional表檔案

  • MaxCompute會按照批處理方式執行DELETEUPDATE作業,每一條語句都會使用資源併產生費用,建議您使用批量方式刪除或更新資料。例如您通過Python指令碼產生並提交了大量行層級更新作業,且每條語句只操作一行或者少量行資料,則每條語句都會產生與SQL掃描輸入資料量對應的費用,並使用相應的計算資源,多條語句累加時將明顯增加費用成本,降低系統效率。命令樣本如下。

    • 推薦方案:

      UPDATE table1 SET col1= (SELECT value1 FROM table2 WHERE table1.id = table2.id AND table1.region = table2.region);
    • 不推薦方案:

      UPDATE table1 SET col1=1 WHERE id='2021063001' AND region='beijing';                 
      UPDATE table1 SET col1=2 WHERE id='2021063002' AND region='beijing';

命令格式

--方式1
UPDATE <table_name> [[AS] alias] SET <col1_name> = <value1> [, <col2_name> = <value2> ...] [WHERE <where_condition>];

--方式2
UPDATE <table_name> [[AS] alias] SET (<col1_name> [, <col2_name> ...]) = (<value1> [, <value2> ...]) [WHERE <where_condition>];

--方式3
UPDATE <table_name> [[AS] alias]
    SET <col1_name> = <value1> [, <col2_name> = <value2>, ...]
    [FROM <additional_tables>]
    [WHERE <where_condition>];

參數說明

  • table_name:必填。待執行UPDATE操作的Transactional表或Delta Table表名稱。

  • alias:可選。表別名。

  • col1_namecol2_name:必填。至少更新一個。待修改行對應的列名稱。

  • value1value2:必填。至少更新一個列值。修改後的新值。

  • where_condition:可選。WHERE子句,用於篩選滿足條件的資料。更多WHERE子句資訊,請參見SELECT文法。如果不帶WHERE子句,會更新表中的所有資料。

  • additional_tables:可選。FROM子句。

    UPDATE支援FROM子句,使用FROM子句時,UPDATE的使用會更加方便,不使用FROM子句與使用FROM子句的對比樣本如下。

    情境

    範例程式碼

    不使用FROM子句

    UPDATE target SET v = 
      (SELECT MIN(v) FROM src GROUP BY k WHERE target.k = src.key)
      WHERE target.k IN (SELECT k FROM src);

    使用FROM子句

    UPDATE target SET v = b.v
      FROM (SELECT k, MIN(v) AS v FROM src GROUP BY k) b
      WHERE target.k = b.k;

    從上述範例程式碼可見:

    • 當用源表的多行資料更新目標表的一行資料的時,由於不知道用哪條源表的資料去更新,所以遇到這種情況需要使用者寫彙總操作來保證資料來源的unique性,可以看出不使用FROM子句時代碼不夠簡潔,使用FROM子句的寫法比較簡潔易懂。

    • 關聯更新的時候,如果只更新交集資料,不使用FROM子句時需要寫額外的where條件,相對於FROM文法而言也不太簡潔。

使用樣本

  • 樣本1:建立非分區表acid_update,並匯入資料,執行UPDATE操作更新滿足指定條件的行對應的列資料。命令樣本如下:

    --建立Transactional表acid_update。  
    CREATE TABLE IF  NOT EXISTS acid_update(id BIGINT) tblproperties ("transactional"="true");
    
    --插入資料。
    INSERT OVERWRITE TABLE acid_update VALUES(1),(2),(3),(2);
    
    --查看插入結果。
    SELECT * FROM acid_update; 
    
    --返回結果
    +------------+
    | id         |
    +------------+
    | 1          |
    | 2          |
    | 3          |
    | 2          |
    +------------+
    
    --將所有id為2的行,id值更新為4。
    UPDATE acid_update SET id = 4 WHERE id = 2; 
    
    --查看更新結果,2被更新為4。
    SELECT * FROM acid_update; 
    
    --返回結果
    +------------+
    | id         |
    +------------+
    | 1          |
    | 3          |
    | 4          |
    | 4          |
    +------------+
  • 樣本2:建立分區表acid_update,並匯入資料,執行UPDATE操作更新滿足指定條件的行對應的列資料。命令樣本如下:

    --建立Transactional表acid_update_pt。 
    CREATE TABLE IF  NOT EXISTS acid_update_pt(id BIGINT) PARTITIONED BY(ds STRING) tblproperties ("transactional"="true");
    
    --添加分區。
    ALTER TABLE acid_update_pt ADD IF  NOT EXISTS PARTITION (ds= '2019');
    
    --插入資料。
    INSERT OVERWRITE TABLE acid_update_pt PARTITION (ds='2019') VALUES(1),(2),(3);
    
    --查看插入結果
    SELECT * FROM acid_update_pt WHERE ds = '2019'; 
    
    --返回結果
    +------------+------------+
    | id         | ds         |
    +------------+------------+
    | 1          | 2019       |
    | 2          | 2019       |
    | 3          | 2019       |
    +------------+------------+
    
    --更新指定行的一列資料,將分區為2019的所有id=2的行,id值更新為4。
    UPDATE acid_update_pt SET id = 4 WHERE ds = '2019' AND id = 2; 
    
    --查看更新結果,2被更新為4。
    SELECT * FROM acid_update_pt WHERE ds = '2019';
    
    --返回結果
    +------------+------------+
    | id         | ds         |
    +------------+------------+
    | 4          | 2019       |
    | 1          | 2019       |
    | 3          | 2019       |
    +------------+------------+
  • 樣本3:建立目標表acid_update_t和關聯表acid_update_s,實現同時更新多列值。命令樣本如下:

    --建立待更新目標Transactional表acid_update_t和關聯表acid_update_s。
    CREATE TABLE IF  NOT EXISTS acid_update_t(id INT,value1 INT,value2 INT) tblproperties ("transactional"="true");
    CREATE TABLE IF  NOT EXISTS acid_update_s(id INT,value1 INT,value2 INT); 
    
    --插入資料。
    INSERT OVERWRITE TABLE acid_update_t VALUES(2,20,21),(3,30,31),(4,40,41);
    INSERT OVERWRITE TABLE acid_update_s VALUES(1,100,101),(2,200,201),(3,300,301);
    
    --方式一:用常量更新。
    UPDATE acid_update_t SET (value1, value2) = (60,61);
    --查詢方式一目標表結果資料。
    SELECT * FROM acid_update_t;
    
    --返回結果
    +------------+------------+------------+
    | id         | value1     | value2     |
    +------------+------------+------------+
    | 2          | 60         | 61         |
    | 3          | 60         | 61         |
    | 4          | 60         | 61         |
    +------------+------------+------------+
    
    --方式二:關聯更新,規則為acid_update_t表左關聯acid_update_s表。
    UPDATE acid_update_t SET (value1, value2) = (SELECT value1, value2 FROM acid_update_s WHERE acid_update_t.id = acid_update_s.id);
    --查詢方式二目標表結果資料。
    SELECT * FROM acid_update_t;
    
    --返回結果
    +------------+------------+------------+
    | id         | value1     | value2     |
    +------------+------------+------------+
    | 2          | 200        | 201        |
    | 3          | 300        | 301        |
    | 4          | NULL       | NULL       |
    +------------+------------+------------+
    
    --方式三(基於“方式二”的結果進行更新):關聯更新,規則為增加過濾條件,只更新交集。
    UPDATE acid_update_t SET (value1, value2) = (SELECT value1, value2 FROM acid_update_s WHERE acid_update_t.id = acid_update_s.id) WHERE acid_update_t.id IN (SELECT id FROM acid_update_s);
    --查詢方式三目標表結果資料。
    SELECT * FROM acid_update_t;
    
    --返回結果
    +------------+------------+------------+
    | id         | value1     | value2     |
    +------------+------------+------------+
    | 2          | 200        | 201        |
    | 3          | 300        | 301        |
    | 4          | NULL       | NULL       |
    +------------+------------+------------+
    
    --方式四(基於“方式三”的結果進行更新):用匯總結果關聯更新。
    UPDATE acid_update_t SET (id, value1, value2) = (SELECT id, MAX(value1),MAX(value2) FROM acid_update_s WHERE acid_update_t.id = acid_update_s.id GROUP BY acid_update_s.id) WHERE acid_update_t.id IN (SELECT id FROM acid_update_s);
    --查詢方式四目標表結果資料。
    SELECT * FROM acid_update_t;
    
    --返回結果
    +------------+------------+------------+
    | id         | value1     | value2     |
    +------------+------------+------------+
    | 2          | 200        | 201        |
    | 3          | 300        | 301        |
    | 4          | NULL       | NULL       |
    +------------+------------+------------+
  • 樣本4:涉及兩個表的簡單關聯查詢,樣本命令如下:

    --建立更新目標表acid_update_t和關聯表acid_update_s 
    CREATE TABLE IF  NOT EXISTS acid_update_t(id BIGINT,value1 BIGINT,value2 BIGINT) tblproperties ("transactional"="true");
    CREATE TABLE IF  NOT EXISTS acid_update_s(id BIGINT,value1 BIGINT,value2 BIGINT);
    
    --插入資料
    INSERT OVERWRITE TABLE acid_update_t VALUES(2,20,21),(3,30,31),(4,40,41);
    INSERT OVERWRITE TABLE acid_update_s VALUES(1,100,101),(2,200,201),(3,300,301);
    
    --查詢acid_update_t表資料
    SELECT * FROM acid_update_t;
    --返回結果
    +------------+------------+------------+
    | id         | value1     | value2     |
    +------------+------------+------------+
    | 2          | 20         | 21         |
    | 3          | 30         | 31         |
    | 4          | 40         | 41         |
    +------------+------------+------------+
    
    --查詢acid_update_s表資料
    SELECT * FROM acid_update_s;
    --返回結果
    +------------+------------+------------+
    | id         | value1     | value2     |
    +------------+------------+------------+
    | 1          | 100        | 101        |
    | 2          | 200        | 201        |
    | 3          | 300        | 301        |
    +------------+------------+------------+
    
    --關聯更新,目標表增加過濾條件,只取交集
    UPDATE acid_update_t SET value1 = b.value1, value2 = b.value2
    FROM acid_update_s b WHERE acid_update_t.id = b.id;
    -- 等價於上面寫法
    UPDATE acid_update_t a SET a.value1 = b.value1, a.value2 = b.value2 
    FROM acid_update_s b WHERE a.id = b.id;
    
    --查看更新結果,20被更新為200,21被更新為201,30被更新為300,31被更新為301
    SELECT * FROM acid_update_t;
    --返回結果
    +------------+------------+------------+
    | id         | value1     | value2     |
    +------------+------------+------------+
    | 4          | 40         | 41         |
    | 2          | 200        | 201        |
    | 3          | 300        | 301        |
    +------------+------------+------------+                          
  • 樣本5:涉及多個表的複雜關聯查詢,樣本命令如下:

    --建立更新目標表acid_update_t和關聯表acid_update_s 
    CREATE TABLE IF  NOT EXISTS acid_update_t(id BIGINT,value1 BIGINT,value2 BIGINT) tblproperties ("transactional"="true");
    CREATE TABLE IF  NOT EXISTS acid_update_s(id BIGINT,value1 BIGINT,value2 BIGINT);
    CREATE TABLE IF  NOT EXISTS acid_update_m(id BIGINT,value1 BIGINT,value2 BIGINT);
    
    --插入資料
    INSERT OVERWRITE TABLE acid_update_t VALUES(2,20,21),(3,30,31),(4,40,41),(5,50,51);
    INSERT OVERWRITE TABLE acid_update_s VALUES (1,100,101),(2,200,201),(3,300,301),(4,400,401),(5,500,501);
    INSERT OVERWRITE TABLE acid_update_m VALUES(3,30,101),(4,400,201),(5,300,301);
    
    --查詢acid_update_t表資料
    SELECT * FROM acid_update_t;
    --返回結果
    +------------+------------+------------+
    | id         | value1     | value2     |
    +------------+------------+------------+
    | 2          | 20         | 21         |
    | 3          | 30         | 31         |
    | 4          | 40         | 41         |
    | 5          | 50         | 51         |
    +------------+------------+------------+
    
    --查詢acid_update_s表資料
    SELECT * FROM acid_update_s;
    --返回結果
    +------------+------------+------------+
    | id         | value1     | value2     |
    +------------+------------+------------+
    | 1          | 100        | 101        |
    | 2          | 200        | 201        |
    | 3          | 300        | 301        |
    | 4          | 400        | 401        |
    | 5          | 500        | 501        |
    +------------+------------+------------+
    
    --查詢acid_update_m表資料
    SELECT * FROM acid_update_m;
    --返回結果
    +------------+------------+------------+
    | id         | value1     | value2     |
    +------------+------------+------------+
    | 3          | 30         | 101        |
    | 4          | 400        | 201        |
    | 5          | 300        | 301        |
    +------------+------------+------------+
    
    --關聯更新,並且在where中同時對原表和目標表進行過濾
    UPDATE acid_update_t 
    SET value1 = acid_update_s.value1, value2 = acid_update_s.value2 
    FROM acid_update_s 
    WHERE acid_update_t.id = acid_update_s.id 
    AND acid_update_s.id > 2 
    AND acid_update_t.value1 NOT IN 
    (SELECT value1 FROM acid_update_m WHERE id = acid_update_t.id) 
    AND acid_update_s.value1 NOT IN 
    (SELECT value1 FROM acid_update_m WHERE id = acid_update_s.id);
    
    --查看更新結果,acid_update_t表只有id為5的資料符合條件,對應value1被更新為500,valu2被更新為501
    SELECT * FROM acid_update_t;
    --返回結果
    +------------+------------+------------+
    | id         | value1     | value2     |
    +------------+------------+------------+
    | 5          | 500        | 501        |
    | 2          | 20         | 21         |
    | 3          | 30         | 31         |
    | 4          | 40         | 41         |
    +------------+------------+------------+
  • 樣本6:建立Delta Table表mf_dt,並匯入資料,執行UPDATE操作刪除滿足指定條件的行。命令樣本如下:

    --建立目標Delta Table表mf_dt。
    CREATE TABLE IF  NOT EXISTS mf_dt (pk BIGINT  NOT NULL PRIMARY KEY, 
                      val  BIGINT NOT NULL) 
                      PARTITIONED BY(dd STRING, hh STRING) 
                      tblproperties ("transactional"="true");
    
    --插入資料
    INSERT OVERWRITE TABLE mf_dt PARTITION (dd='01', hh='02') 
                     VALUES (1, 1), (2, 2), (3, 3);
    
    --查看插入結果                 
    SELECT * FROM mf_dt WHERE dd='01' AND hh='02';
    --返回結果
    +------------+------------+----+----+
    | pk         | val        | dd | hh |
    +------------+------------+----+----+
    | 1          | 1          | 01 | 02 |
    | 3          | 3          | 01 | 02 |
    | 2          | 2          | 01 | 02 |
    +------------+------------+----+----+
    
    --更新指定行的一列資料,將分區為01和02的所有pk=3的行,val值更新為30。
    --方法一
    UPDATE mf_dt SET val = 30 WHERE pk = 3 AND dd='01' AND hh='02';
    
    --方法二
    UPDATE mf_dt SET val = delta.val 
                  FROM (SELECT pk, val FROM VALUES (3, 30) t (pk, val)) delta 
                  WHERE delta.pk = mf_dt.pk AND mf_dt.dd='01' AND mf_dt.hh='02';
    
    --查看更新結果。
    SELECT * FROM mf_dt WHERE dd='01' AND hh='02';
    --返回結果,pk=3的行val值被更新為30。
    +------------+------------+----+----+
    | pk         | val        | dd | hh |
    +------------+------------+----+----+
    | 1          | 1          | 01 | 02 |
    | 3          | 30         | 01 | 02 |
    | 2          | 2          | 01 | 02 |
    +------------+------------+----+----+

相關命令

  • DELETE:用於刪除Transactional分區表或非分區表中滿足指定條件的單行或多行資料。

  • ALTER TABLE:合并Transactional表檔案。