A instrução UPDATE modifica valores de colunas em uma ou mais linhas de uma Transactional Table ou Delta Table.
Pré-requisitos
Antes de executar uma instrução DELETE ou UPDATE, verifique se você tem:
Permissões Selecione e Atualize na Transactional Table ou Delta Table de destino
Para obter mais informações, consulte Permissões do MaxCompute.
Limitações
As instruções
UPDATEeDELETEfuncionam apenas em Transactional Tables e Delta Tables. Para detalhes de configuração, consulte Parâmetros para Transaction Table e Delta Table.A operação
UPDATEem uma Delta Table não pode modificar colunas de chave primária (PK).
Sintaxe
-- Method 1: Update individual columns
UPDATE <table_name> [[AS] alias] SET <col1_name> = <value1> [, <col2_name> = <value2> ...] [WHERE <where_condition>];
-- Method 2: Update multiple columns as a tuple
UPDATE <table_name> [[AS] alias] SET (<col1_name> [, <col2_name> ...]) = (<value1> [, <value2> ...]) [WHERE <where_condition>];
-- Method 3: Update with a FROM clause (join update)
UPDATE <table_name> [[AS] alias]
SET <col1_name> = <value1> [, <col2_name> = <value2>, ...]
[FROM <additional_tables>]
[WHERE <where_condition>];
Parâmetros
Parâmetros obrigatórios
|
Parâmetro |
Descrição |
|
|
Nome da Transactional Table ou Delta Table a atualizar. |
|
|
Colunas a atualizar. Especifique pelo menos uma coluna. |
|
|
Novos valores para as colunas especificadas. Forneça pelo menos um valor. |
Parâmetros opcionais
|
Parâmetro |
Descrição |
Padrão |
|
|
Alias para a tabela de destino. |
Sem alias |
|
|
Expressão de filtro que define as linhas a atualizar. Consulte a Sintaxe SELECT para ver as expressões suportadas. |
Se omitido, todas as linhas da tabela serão atualizadas. |
|
|
Uma ou mais tabelas de origem para atualização com junção, especificadas na cláusula FROM. |
Sem junção |
Cláusula FROM
A cláusula FROM permite atualizar linhas na tabela de destino com base em linhas correspondentes de uma ou mais tabelas de origem. Essa abordagem simplifica atualizações com junção em comparação à sintaxe baseada em subconsultas.
A tabela a seguir compara a mesma atualização com junção escrita com e sem a cláusula FROM.
|
Abordagem |
Exemplo |
|
Sem cláusula FROM |
|
|
Com cláusula FROM |
|
A versão com cláusula FROM é mais curta e fácil de ler. A versão com subconsulta exige uma condição WHERE adicional (para atualizar apenas a interseção) e uma agregação na subconsulta (para garantir que a origem produza um único valor por linha de destino).
Linhas com múltiplas junções
Uma linha com múltiplas junções ocorre quando uma linha de destino corresponde a mais de uma linha na tabela de origem durante uma atualização com junção. O resultado é não determinístico: o MaxCompute utiliza uma das linhas de origem correspondentes para realizar a atualização, mas não garante qual delas será usada.
Para evitar atualizações não determinísticas, use uma agregação em uma subconsulta e garanta que cada linha de destino corresponda a exatamente um valor de origem:
-- Produces a unique value per key before joining
UPDATE target SET v = b.v
FROM (SELECT k, MIN(v) AS v FROM src GROUP BY k) b
WHERE target.k = b.k;
Observações de uso
Escolha a operação adequada para sua carga de trabalho
|
Cenário |
Operação recomendada |
|
Poucas linhas para atualizar; atualizações e leituras subsequentes pouco frequentes |
|
|
Mais de 5% das linhas para atualizar esporadicamente; leituras subsequentes frequentes |
|
Por exemplo, se um pipeline exclui ou atualiza 10% das linhas de uma tabela dez vezes ao dia, compare o custo total e a degradação do desempenho de leitura causada por operações repetidas de DELETE/UPDATE com o uso de INSERT OVERWRITE em cada execução. Em seguida, escolha a abordagem mais eficiente para sua carga de trabalho. Consulte Inserir ou sobrescrever dados (INSERT INTO \| INSERT OVERWRITE).
Atualize em lotes, não linha por linha
O MaxCompute executa cada instrução UPDATE como um processo em lote. Cada instrução consome recursos e gera custos com base no volume de dados verificados, independentemente da quantidade de linhas alteradas. Enviar muitas instruções no nível de linha — por exemplo, a partir de um script Python que gera um UPDATE por linha — acumula altos custos e reduz a eficiência.
Sempre que possível, consolide as atualizações em uma única instrução:
-- Recommended: one statement updates all matching rows
UPDATE table1 SET col1 = (SELECT value1 FROM table2 WHERE table1.id = table2.id AND table1.region = table2.region);
-- Not recommended: one statement per row
UPDATE table1 SET col1 = 1 WHERE id = '2021063001' AND region = 'beijing';
UPDATE table1 SET col1 = 2 WHERE id = '2021063002' AND region = 'beijing';
Impacto de armazenamento do DELETE e UPDATE
Excluir ou atualizar linhas gera arquivos Delta em vez de reduzir imediatamente o armazenamento. Para recuperar espaço após várias operações, mescle os arquivos base e os arquivos Delta da tabela. Consulte Mesclar arquivos de tabela transacional.
Exemplos
Exemplo 1: Atualizar linhas em uma tabela não particionada
Crie uma Transactional Table, insira dados e atualize todas as linhas onde id = 2.
-- Create a Transactional table
CREATE TABLE IF NOT EXISTS acid_update(id BIGINT) tblproperties ("transactional"="true");
-- Insert data
INSERT OVERWRITE TABLE acid_update VALUES(1),(2),(3),(2);
-- Verify the inserted data
SELECT * FROM acid_update;
-- Result:
-- +------------+
-- | id |
-- +------------+
-- | 1 |
-- | 2 |
-- | 3 |
-- | 2 |
-- +------------+
-- Update: set id to 4 for all rows where id is 2
UPDATE acid_update SET id = 4 WHERE id = 2;
-- Verify the result
SELECT * FROM acid_update;
-- Result: both rows with id=2 are updated to 4
-- +------------+
-- | id |
-- +------------+
-- | 1 |
-- | 3 |
-- | 4 |
-- | 4 |
-- +------------+
Exemplo 2: Atualizar linhas em uma tabela particionada
Crie uma Transactional Table particionada, insira dados na partição ds='2019' e atualize as linhas dessa partição.
-- Create a partitioned Transactional table
CREATE TABLE IF NOT EXISTS acid_update_pt(id BIGINT) PARTITIONED BY(ds STRING) tblproperties ("transactional"="true");
-- Add a partition
ALTER TABLE acid_update_pt ADD IF NOT EXISTS PARTITION (ds='2019');
-- Insert data
INSERT OVERWRITE TABLE acid_update_pt PARTITION (ds='2019') VALUES(1),(2),(3);
-- Verify the inserted data
SELECT * FROM acid_update_pt WHERE ds = '2019';
-- Result:
-- +------------+------------+
-- | id | ds |
-- +------------+------------+
-- | 1 | 2019 |
-- | 2 | 2019 |
-- | 3 | 2019 |
-- +------------+------------+
-- Update: set id to 4 for the row where ds='2019' and id=2
UPDATE acid_update_pt SET id = 4 WHERE ds = '2019' AND id = 2;
-- Verify the result
SELECT * FROM acid_update_pt WHERE ds = '2019';
-- Result:
-- +------------+------------+
-- | id | ds |
-- +------------+------------+
-- | 4 | 2019 |
-- | 1 | 2019 |
-- | 3 | 2019 |
-- +------------+------------+
Exemplo 3: Atualizar várias colunas usando quatro métodos
Este exemplo demonstra quatro maneiras de atualizar várias colunas em uma Transactional Table por meio de junção com uma tabela de origem.
-- Create the target Transactional table and a source table
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 data
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);
-- Method 1: Update with constant values (updates all rows)
UPDATE acid_update_t SET (value1, value2) = (60, 61);
SELECT * FROM acid_update_t;
-- Result:
-- +------------+------------+------------+
-- | id | value1 | value2 |
-- +------------+------------+------------+
-- | 2 | 60 | 61 |
-- | 3 | 60 | 61 |
-- | 4 | 60 | 61 |
-- +------------+------------+------------+
-- Method 2: Join update (left join from acid_update_t to acid_update_s)
-- Rows in acid_update_t with no match in acid_update_s are set to NULL
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;
-- Result:
-- +------------+------------+------------+
-- | id | value1 | value2 |
-- +------------+------------+------------+
-- | 2 | 200 | 201 |
-- | 3 | 300 | 301 |
-- | 4 | NULL | NULL |
-- +------------+------------+------------+
-- Method 3: Join update restricted to the intersection (rows with a matching id in both tables)
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;
-- Result: same as Method 2 because id=4 has no match and is unchanged from the Method 2 result
-- +------------+------------+------------+
-- | id | value1 | value2 |
-- +------------+------------+------------+
-- | 2 | 200 | 201 |
-- | 3 | 300 | 301 |
-- | 4 | NULL | NULL |
-- +------------+------------+------------+
-- Method 4: Join update with aggregation (uses MAX to handle multiple matching source rows)
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;
-- Result:
-- +------------+------------+------------+
-- | id | value1 | value2 |
-- +------------+------------+------------+
-- | 2 | 200 | 201 |
-- | 3 | 300 | 301 |
-- | 4 | NULL | NULL |
-- +------------+------------+------------+
Exemplo 4: Atualização com junção usando a cláusula FROM (duas tabelas)
A cláusula FROM simplifica atualizações com junção. Ambas as instruções abaixo produzem o mesmo resultado.
-- Create the target and source tables
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 data
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);
-- Join update using the FROM clause
UPDATE acid_update_t SET value1 = b.value1, value2 = b.value2
FROM acid_update_s b WHERE acid_update_t.id = b.id;
-- Equivalent statement using a table alias for the target table
UPDATE acid_update_t a SET a.value1 = b.value1, a.value2 = b.value2
FROM acid_update_s b WHERE a.id = b.id;
-- Verify the result: rows with id=2 and id=3 are updated; id=4 has no match and is unchanged
SELECT * FROM acid_update_t;
-- Result:
-- +------------+------------+------------+
-- | id | value1 | value2 |
-- +------------+------------+------------+
-- | 4 | 40 | 41 |
-- | 2 | 200 | 201 |
-- | 3 | 300 | 301 |
-- +------------+------------+------------+
Exemplo 5: Atualização com junção usando múltiplas tabelas de origem e condições de filtro
Este exemplo junta três tabelas e aplica filtros tanto às tabelas de origem quanto à de destino. Apenas as linhas que satisfazem todas as condições são atualizadas.
-- Create three tables
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 data
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);
-- Join update: filter both the source and target tables in the WHERE clause
-- Only rows with id > 2 where neither the target's value1 nor the source's value1
-- appears in acid_update_m for the same id are updated
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);
-- Verify the result: only id=5 satisfies all conditions
SELECT * FROM acid_update_t;
-- Result:
-- +------------+------------+------------+
-- | id | value1 | value2 |
-- +------------+------------+------------+
-- | 5 | 500 | 501 |
-- | 2 | 20 | 21 |
-- | 3 | 30 | 31 |
-- | 4 | 40 | 41 |
-- +------------+------------+------------+
Exemplo 6: Atualizar linhas em uma Delta Table
Crie uma Delta Table, insira dados e atualize a coluna val de uma linha específica usando dois métodos equivalentes.
-- Create a Delta Table with a primary key
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 data
INSERT OVERWRITE TABLE mf_dt PARTITION (dd='01', hh='02')
VALUES (1, 1), (2, 2), (3, 3);
-- Verify the inserted data
SELECT * FROM mf_dt WHERE dd='01' AND hh='02';
-- Result:
-- +------------+------------+----+----+
-- | pk | val | dd | hh |
-- +------------+------------+----+----+
-- | 1 | 1 | 01 | 02 |
-- | 3 | 3 | 01 | 02 |
-- | 2 | 2 | 01 | 02 |
-- +------------+------------+----+----+
-- Method 1: Update with a direct value
UPDATE mf_dt SET val = 30 WHERE pk = 3 AND dd='01' AND hh='02';
-- Method 2: Update using a FROM clause with inline values
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';
-- Verify the result
SELECT * FROM mf_dt WHERE dd='01' AND hh='02';
-- Result: val for pk=3 is updated from 3 to 30
-- +------------+------------+----+----+
-- | pk | val | dd | hh |
-- +------------+------------+----+----+
-- | 1 | 1 | 01 | 02 |
-- | 3 | 30 | 01 | 02 |
-- | 2 | 2 | 01 | 02 |
-- +------------+------------+----+----+
Próximos passos
DELETE: Exclua linhas de uma Transactional Table ou Delta Table.
ALTER TABLE: Mescle arquivos base e arquivos Delta para reduzir o armazenamento após múltiplas operações de atualização ou exclusão.