UPDATE 文は、トランザクションテーブルまたは Delta テーブルの 1 つ以上の列の値を更新します。
前提条件
DELETE 文または UPDATE 文を実行するトランザクションテーブルに対する Select 権限と Update 権限が付与されている必要があります。詳細については、「MaxCompute 権限」をご参照ください。
制限事項
DELETEおよびUPDATE機能は、トランザクションテーブルと Delta テーブルでのみ使用でき、次の制限があります。説明トランザクションテーブルと Delta テーブルの詳細については、「トランザクションテーブルと Delta テーブルのパラメーター」をご参照ください。
Delta テーブルの
UPDATE構文は、プライマリキー (PK) 列の変更をサポートしていません。
注意事項
DELETE または UPDATE 操作を使用してテーブルまたはパーティションのデータを削除または更新する場合は、次の項目を考慮してください。
テーブル内の少量のデータを削除または更新し、その操作とその後の読み取りの両方が頻繁でない場合は、
DELETEおよびUPDATE操作を使用します。複数の削除または更新操作を実行した後は、テーブルのベースファイルと Delta ファイルをマージして、ストレージフットプリントを削減します。詳細については、「トランザクションテーブルのマージ」をご参照ください。多くの行 (5% 超) を頻繁に削除または更新するのではなく、テーブルに対するその後の読み取り操作が頻繁である場合は、
INSERT OVERWRITEまたはINSERT INTOを使用します。詳細については、「データの挿入または上書き (INSERT INTO | INSERT OVERWRITE)」をご参照ください。たとえば、1 日に 10 回、データの 10% を削除または更新するビジネスシナリオを考えます。
DELETEおよびUPDATE操作によるコストとその後の読み取りパフォーマンスの低下が、各操作でINSERT OVERWRITEまたはINSERT INTOを使用する場合よりも低いかどうかを評価します。特定のシナリオで 2 つのメソッドの効率を比較し、より適切なオプションを選択してください。データを削除すると Delta ファイルが生成されます。つまり、この操作ではストレージはすぐには削減されません。
DELETE操作を使用してストレージを削減したい場合は、テーブルのベースファイルと Delta ファイルをマージする必要があります。詳細については、「トランザクションテーブルのマージ」をご参照ください。MaxCompute は
DELETEおよびUPDATEジョブをバッチプロセスとして実行します。各文はリソースを消費し、料金が発生します。データはバッチで削除または更新する必要があります。たとえば、Python スクリプトを使用して、各文が 1 行または数行のみを操作する多数の行レベルの更新ジョブを生成して送信する場合、各文は 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='北京'; UPDATE table1 SET col1=2 WHERE id='2021063002' AND region='北京';
構文
-- メソッド 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操作の対象となるトランザクションテーブルまたは Delta テーブルの名前。alias:任意。テーブルのエイリアス。
col1_name、col2_name:必須。変更する列の名前。少なくとも 1 つの列を更新する必要があります。
value1、value2:必須。列の新しい値。少なくとも 1 つの列の値を更新する必要があります。
where_condition:任意。データをフィルターする WHERE 句。WHERE 句の詳細については、「SELECT 構文」をご参照ください。WHERE 句を含めない場合、テーブル内のすべてのデータが更新されます。
additional_tables:任意。FROM 句。
UPDATE文は FROM 句をサポートしており、これによりUPDATE文を簡略化できます。次の表は、FROM 句を使用する UPDATE 文と使用しない UPDATE 文を比較したものです。シナリオ
サンプルコード
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;コード例が示すように:
ソーステーブルの複数の行を使用してターゲットテーブルの 1 行を更新する場合、システムはどのソース行を使用すればよいかわからないため、集約操作を使用してソースデータが一意であることを保証する必要があります。`FROM` 句を使用しない構文は、あまり簡潔ではありません。`FROM` 句を使用する構文は、よりシンプルで理解しやすいです。
結合更新を実行するときに、データの積集合のみを更新したい場合、`FROM` 句を使用しない構文は追加の `WHERE` 条件が必要となり、`FROM` 句を使用する構文よりも簡潔ではありません。
例
例 1:acid_update という名前の非パーティションテーブルを作成し、データをインポートしてから、
UPDATE操作を実行して、指定された条件を満たす行の列を更新します。サンプルコマンドは次のとおりです。-- 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操作を実行して、指定された条件を満たす行の列を更新します。サンプルコマンドは次のとおりです。-- 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 を作成して、複数の列値を同時に更新します。サンプルコマンドは次のとおりです。
-- 更新対象のターゲットトランザクションテーブル 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); -- メソッド 1:定数で更新します。 UPDATE acid_update_t SET (value1, value2) = (60,61); -- メソッド 1 のターゲットテーブルの結果データをクエリします。 SELECT * FROM acid_update_t; -- 次の結果が返されます。 +------------+------------+------------+ | id | value1 | value2 | +------------+------------+------------+ | 2 | 60 | 61 | | 3 | 60 | 61 | | 4 | 60 | 61 | +------------+------------+------------+ -- メソッド 2:結合更新。ルールは 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); -- メソッド 2 のターゲットテーブルの結果データをクエリします。 SELECT * FROM acid_update_t; -- 次の結果が返されます。 +------------+------------+------------+ | id | value1 | value2 | +------------+------------+------------+ | 2 | 200 | 201 | | 3 | 300 | 301 | | 4 | NULL | NULL | +------------+------------+------------+ -- メソッド 3 (メソッド 2 の結果に基づく更新):結合更新。ルールは、フィルター条件を追加して積集合のみを更新することです。 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); -- メソッド 3 のターゲットテーブルの結果データをクエリします。 SELECT * FROM acid_update_t; -- 次の結果が返されます。 +------------+------------+------------+ | id | value1 | value2 | +------------+------------+------------+ | 2 | 200 | 201 | | 3 | 300 | 301 | | 4 | NULL | NULL | +------------+------------+------------+ -- メソッド 4 (メソッド 3 の結果に基づく更新):集約結果による結合更新。 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); -- メソッド 4 のターゲットテーブルの結果データをクエリします。 SELECT * FROM acid_update_t; -- 次の結果が返されます。 +------------+------------+------------+ | id | value1 | value2 | +------------+------------+------------+ | 2 | 200 | 201 | | 3 | 300 | 301 | | 4 | NULL | NULL | +------------+------------+------------+例 4:2 つのテーブルを含む単純な結合クエリ。サンプルコマンドは次のとおりです。
-- 更新対象のターゲットテーブル 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); -- 更新結果を表示します。id が 5 の acid_update_t テーブルのデータのみが条件を満たします。対応する value1 は 500 に、value2 は 501 に更新されます。 SELECT * FROM acid_update_t; -- 次の結果が返されます。 +------------+------------+------------+ | id | value1 | value2 | +------------+------------+------------+ | 5 | 500 | 501 | | 2 | 20 | 21 | | 3 | 30 | 31 | | 4 | 40 | 41 | +------------+------------+------------+例 6:次のコマンドは、mf_dt という名前の Delta テーブルを作成し、データをインポートし、
UPDATE操作を実行して指定された条件を満たす行を更新する方法の例です。-- mf_dt という名前のターゲット Delta テーブルを作成します。 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 に設定します。 -- メソッド 1 UPDATE mf_dt SET val = 30 WHERE pk = 3 AND dd='01' AND hh='02'; -- メソッド 2 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:指定された条件を満たす 1 つ以上の行をトランザクションテーブルまたは Delta テーブルから削除します。
-
ALTER TABLE:トランザクションテーブルのファイルをマージします。