Zaktualizuj lub wstaw (wiele wierszy i kolumn) z podzapytania w PostgreSQL

106

Próbuję zrobić coś takiego w 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)

Ale punkt 1 nie jest możliwy nawet z postgres 9.0, jak wspomniano w dokumentacji ( http://www.postgresql.org/docs/9.0/static/sql-update.html )

Również punkt 2 wydaje się nie działać. Otrzymuję następujący błąd: podzapytanie musi zwracać tylko jedną kolumnę.

Mam nadzieję, że ktoś ma dla mnie obejście. w przeciwnym razie zapytania zajmie trochę czasu :(.

FYI: Staram się wybierać różne kolumny z kilku tabel i przechowywać je w tabeli tymczasowej, aby inna aplikacja mogła łatwo pobrać przygotowane dane.

dforce
źródło

Odpowiedzi:

175

W przypadku UPDATE

Posługiwać się:

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

W przypadku INSERT

Posługiwać się:

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

Nie potrzebujesz VALUESskładni, jeśli używasz SELECT do wypełnienia wartości INSERT.

Kucyki OMG
źródło
1
Czy można połączyć Update & Insert tak, aby w przypadku niepowodzenia jednego z nich, drugi został użyty bez zgłaszania błędu (niezależnie dla każdego wiersza). Myślę, że byłoby to pełniejsze rozwiązanie tego pytania (na przykład: stackoverflow.com/a/6527838/781695 )
użytkownik
26

Odpowiedź OMG Ponies działa idealnie, ale na wypadek, gdybyś potrzebował czegoś bardziej złożonego, oto przykład nieco bardziej zaawansowanego zapytania aktualizacyjnego:

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
źródło
1
Jesteś najlepszy :) :)
Ashwini
1
idealny. działa to najlepiej, gdy musisz wybrać podzbiór na podstawie warunku dotyczącego samej zaktualizowanej tabeli.
mythicalcoder
@David Namenyi Czy możesz wyjaśnić to pytanie?
Chintan Pathak
15
UPDATE table1 SET (col1, col2) = (col2, col3) FROM othertable WHERE othertable.col1 = 123;
Walter
źródło