Atualizar ou inserir (várias linhas e colunas) da subconsulta no PostgreSQL

106

Estou tentando fazer algo assim no postgres:

  • UPDATE table1 SET (col1, col2) = (SELECT col2, col3 FROM othertable WHERE othertable.col1 = 123);

  • INSERT INTO table1 (col1, col2) VALUES (SELECT col1, col2 FROM othertable)

Mas o ponto 1 não é possível mesmo com o postgres 9.0 conforme mencionado nos documentos ( http://www.postgresql.org/docs/9.0/static/sql-update.html )

Além disso, o ponto 2 parece não funcionar. Estou recebendo o seguinte erro: a subconsulta deve retornar apenas uma coluna.

Espero que alguém tenha uma solução alternativa para mim. caso contrário, as consultas demorarão muito tempo :(.

Para sua informação: Estou tentando selecionar diferentes colunas de várias tabelas e armazená-las em uma tabela temporária, para que outro aplicativo possa buscar facilmente os dados preparados.

dforce
fonte

Respostas:

175

Para o UPDATE

Usar:

UPDATE table1 
   SET col1 = othertable.col2,
       col2 = othertable.col3 
  FROM othertable 
 WHERE othertable.col1 = 123;

Para o INSERT

Usar:

INSERT INTO table1 (col1, col2) 
SELECT col1, col2 
  FROM othertable

Você não precisa da VALUESsintaxe se estiver usando um SELECT para preencher os valores INSERT.

Pôneis OMG
fonte
1
É possível combinar Atualizar e Inserir para que se um falhar, o outro seja usado sem lançar um erro (independentemente para cada linha). Acho que seria uma solução mais completa para a questão (por exemplo: stackoverflow.com/a/6527838/781695 )
usuário
26

A resposta do OMG Ponies funciona perfeitamente, mas caso você precise de algo mais complexo, aqui está um exemplo de uma consulta de atualização um pouco mais avançada:

UPDATE table1 
SET col1 = subquery.col2,
    col2 = subquery.col3 
FROM (
    SELECT t2.foo as col1, t3.bar as col2, t3.foobar as col3 
    FROM table2 t2 INNER JOIN table3 t3 ON t2.id = t3.t2_id
    WHERE t2.created_at > '2016-01-01'
) AS subquery
WHERE table1.id = subquery.col1;
David Namenyi
fonte
1
Você é o melhor :) :)
Ashwini
1
perfeito. isso funciona melhor quando você precisa escolher um subconjunto com base em uma condição que envolve a própria tabela atualizada.
codificador mítico
@David Namenyi você pode explicar essa consulta?
Chintan Pathak
15
UPDATE table1 SET (col1, col2) = (col2, col3) FROM othertable WHERE othertable.col1 = 123;
Walter
fonte