Aktualisieren Sie alle Spalten aus einer anderen Tabelle

13

Ich muss eine Tabelle von einer anderen aktualisieren, und ich muss alle Spalten aktualisieren. Gibt es neben der Auflistung aller Spalten in der SETKlausel eine Möglichkeit, alle auf einmal zu aktualisieren? So was:

update tableA
set * = tableB.*
from tableB where tableA.id = tableB.id

Ich habe es in psql versucht, es funktioniert nicht. Ich muss jede Spalte so auflisten:

update tableA
set c1 = tableB.c1, c2 = tableB.c2, ...
from tableB where tableA.id = tableB.id

tableBVerwendung erstellt wird create .. like tableA. Sie sind also im Grunde identisch. Der Grund dafür ist, dass ich CSV-Daten in eine temporäre Tabelle laden tableBund dann tableAbasierend auf den neuen Daten in aktualisieren muss tableB. tableAmuss so wenig wie möglich gesperrt werden und tableAmuss Integrität bewahren. Ich bin mir nicht sicher, ob "Löschen und dann einfügen" eine gute Option ist.

odieatla
quelle
1
Ich habe mit deinem zweiten Code getestet, es funktioniert! Sie sollten zwei Themen lesen : dba.stackexchange.com/questions/58371/… , dba.stackexchange.com/questions/59458/…
Luan Huynh

Antworten:

12

Es gibt keine Syntaxvariante, mit der Sie die gesamte Zeile auf einmal aktualisieren können. Es gibt jedoch eine kürzere Form als bisher.

Außerdem möchten Sie nicht alle Spalten aktualisieren. Die WHEREBedingung an id setzt mindestens eine Spalte ( id) nach unten , um unverändert zu bleiben. Aber das ist nur eine Kleinigkeit.

UPDATE table_a a
SET    (  c1,   c2, ...)
     = (b.c1, b.c2, ...)
FROM   table_b b
WHERE  a.id = b.id;

Weitere Details in dieser verwandten Antwort:
Massenaktualisierung aller Spalten

DELETE / INSERT

Intern fügt aufgrund des MVCC-Modells von Postgres jeder UPDATEeffektiv eine neue Zeile ein und markiert die alte als veraltet. Hinter den Vorhängen gibt es also keinen großen Unterschied zwischen UPDATEund DELETEplus INSERT.
Es gibt einige Details für die UPDATERoute:

  • HEISSES UPDATE.
  • TOAST-Tabellen: Wenn Sie über große Spalten verfügen, wird der Inhalt möglicherweise "out-of-line" in TOAST-Tabellen gespeichert, und die neue Zeilenversion kann auf dieselbe Zeile in der TOAST-Tabelle verweisen, wenn die getoasteten Spalten unverändert bleiben.
  • Die Indexpflege kann bei Updates günstiger sein.

Ansonsten sollte die Sperrung ungefähr gleich sein. In beiden Fällen benötigen Sie eine exklusive Sperre für betroffene Zeilen. Mach es einfach schnell.
Wenn Sie mit einer großen Anzahl von Zeilen arbeiten und keinen konsistenten Status benötigen (alle Zeilen oder keine), können Sie den Vorgang in mehrere Stapel aufteilen. (Separate Transaktionen!) Erhöht die Gesamtkosten, hält aber die Sperrzeit pro Zeile kürzer.

Erwin Brandstetter
quelle
3
DELETE / INSERTkann auch unerwünschte oder einfach andere (kaskadenartige oder ausgelöste) Effekte haben als die UPDATE.
Ypercubeᵀᴹ
Es ist korrekt, aber Sie sollten den Alias-Teil von table_a aktualisieren. table_a (die aktualisierte Tabelle) kann keinen Alias ​​abrufen.
Nur ein weiterer Code Lover