Wie man ein Update macht + PostgreSQL beitreten?

Grundsätzlich möchte ich das tun:

update vehicles_vehicle v join shipments_shipment s on v.shipment_id=s.id set v.price=s.price_per_vehicle; 

Ich bin mir ziemlich sicher, dass das in MySQL funktionieren würde (mein Hintergrund), aber es scheint nicht in Postgres zu funktionieren. Der Fehler, den ich bekomme, ist:

 ERROR: syntax error at or near "join" LINE 1: update vehicles_vehicle v join shipments_shipment s on v.shi... ^ 

Sicherlich gibt es einen einfachen Weg, aber ich kann die richtige Syntax nicht finden. Also, wie würde ich das in PostgreSQL schreiben?

   

Die UPDATE-Syntax lautet:

 [WITH [RECURSIVE] with_query [, ...]]
 UPDATE [ONLY] Tabelle [[AS] Alias]
     SET {Spalte = {Ausdruck |  DEFAULT} |
           (Spalte [, ...]) = ({Ausdruck | DEFAULT} [, ...])} [, ...]
     [FROM aus Liste]
     [WHERE Bedingung |  WHERE CURRENT von Cursorname]
     [RÜCKGABE * |  Ausgabe_Ausdruck [[AS] Ausgabe_Name] [, ...]]

In deinem Fall denke ich, dass du das willst:

 UPDATE vehicles_vehicle AS v SET price = s.price_per_vehicle FROM shipments_shipment AS s WHERE v.shipment_id = s.id 

Lassen Sie mich ein wenig mehr an meinem Beispiel erklären.

Aufgabe: Korrekte Info, wo Abiturienten (Studenten, die kurz vor dem Abitur sind) früher Anträge gestellt haben, als sie Schulzeugnisse erhalten haben (ja, sie haben früher Zertifikate bekommen, als sie ausgestellt wurden (nach Zertifikatsdatum angegeben) Erhöhen Sie das Antragsdatum der Anwendung, um das Ausstellungsdatum des Zertifikats zu berücksichtigen.

So. nächste MySQL-ähnliche statement:

 UPDATE applications a JOIN ( SELECT ap.id, ab.certificate_issued_at FROM abiturients ab JOIN applications ap ON ab.id = ap.abiturient_id WHERE ap.documents_taken_at::date < ab.certificate_issued_at ) b ON a.id = b.id SET a.documents_taken_at = b.certificate_issued_at; 

Wird so postgreSQL-ähnlich

 UPDATE applications a SET documents_taken_at = b.certificate_issued_at -- we can reference joined table here FROM abiturients b -- joined table WHERE a.abiturient_id = b.id AND -- JOIN ON clause a.documents_taken_at::date < b.certificate_issued_at -- Subquery WHERE 

Wie Sie sehen können, ist die ON Klausel der ursprünglichen Unterabfrage JOIN zu einer der WHERE Bedingungen geworden, die von AND mit anderen verbunden werden, die ohne Änderungen aus der Unterabfrage verschoben wurden. Und es besteht keine Notwendigkeit, die Tabelle mit sich selbst zu verbinden (wie es in der Unterabfrage der Fall war).

Die Antwort von Mark Byers ist in dieser Situation optimal. In komplexeren Situationen können Sie jedoch die select-Abfrage verwenden, die rowids und berechnete Werte zurückgibt und sie wie folgt an die Update-Abfrage anhängen:

 with t as ( -- Any generic query which returns rowid and corresponding calculated values select t1.id as rowid, f(t2, t2) as calculatedvalue from table1 as t1 join table2 as t2 on t2.referenceid = t1.id ) update t1 set value = t.calculatedvalue from t where id = t.rowid 

Mit diesem Ansatz können Sie Ihre Auswahlabfrage entwickeln und testen und sie in zwei Schritten in die Aktualisierungsabfrage konvertieren.

In Ihrem Fall lautet die Ergebnisabfrage also:

 with t as ( select v.id as rowid, s.price_per_vehicle as calculatedvalue from vehicles_vehicle v join shipments_shipment s on v.shipment_id = s.id ) update vehicles_vehicle set price = t.calculatedvalue from t where id = t.rowid 

Beachten Sie, dass Spaltenaliasnamen obligatorisch sind, ansonsten wird PostgreSQL über die Mehrdeutigkeit der Spaltennamen klagen.

Für diejenigen, die einen Join machen möchten, können Sie auch verwenden:

 UPDATE a SET price = b_alias.unit_price FROM a as a_alias LEFT JOIN b as b_alias ON a_alias.b_fk = b_alias.id WHERE a_alias.unit_name LIKE 'some_value' AND a.id = a_alias.id; 

Sie können die a_alias im SET-Bereich rechts vom Gleichheitszeichen verwenden, falls erforderlich. Die Felder auf der linken Seite des Gleichheitszeichens erfordern keine Tabellenreferenz, da sie als aus der ursprünglichen Tabelle “a” stammend betrachtet werden.

Auf geht’s:

 update vehicles_vehicle v set price=s.price_per_vehicle from shipments_shipment s where v.shipment_id=s.id; 

Einfach, wie ich es schaffen könnte. Danke Leute!

Kann das auch tun:

 update vehicles_vehicle set price=s.price_per_vehicle from vehicles_vehicle v join shipments_shipment s on v.shipment_id=s.id; 

Aber dann hast du die Vehikel-Tabelle zweimal drin, und du darfst sie nur einmal aliasieren, und du kannst den Alias ​​nicht im Set-Teil verwenden.

Hier ist eine einfache SQL, die Mid_Name in der Name3-Tabelle mit dem Middle_Name-Feld von Name aktualisiert:

 update name3 set mid_name = name.middle_name from name where name3.person_id = name.person_id;