如何在PostgreSQL中进行更新+join?

基本上我想这样做:

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

我敢肯定,这将在MySQL(我的背景)工作,但它似乎并没有在postgres工作。 我得到的错误是:

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

当然有一个简单的方法来做到这一点,但我找不到合适的语法。 那么,我将如何在PostgreSQL中编写这个?

UPDATE语法是:

 [WITH [RECURSIVE] with_query [,...]]
 UPDATE [ONLY]表[[AS]别名]
     SET {column = {expression |  DEFAULT} |
           (column [,...])=({expression | DEFAULT} [,...])} [,...]
     [FROM from_list]
     [哪里条件|  WHERE CURRENT OF cursor_name]
     [返回* |  output_expression [[AS] output_name] [,...]]

在你的情况下,我想你想这样做:

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

让我再以我的例子来解释一下。

任务:正确的信息,在哪里(即将离开中学的学生)已经提前向大学提出申请,比获得学校证书(是的,他们获得了证书的时间早于他们的证书发放date)。增加申请提交date以适应证书颁发date。

从而。 下一个类似MySQL的声明:

 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; 

以这种方式成为PostgreSQL

 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 

正如你所看到的,原来的子查询JOINON子句已经成为WHERE条件之一,这个条件由AND与其他的子元素相结合,这些条件已经从子查询中移除了,没有任何变化。 而且不再需要与自己JOIN表(就像在子查询中一样)。

马克·拜尔斯的答案在这种情况下是最佳的。 虽然在更复杂的情况下,您可以select返回rowid和计算值的查询,并将其附加到更新查询中,如下所示:

 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 

这种方法可以让您开发和testing您的select查询,并分两步将其转换为更新查询。

所以在你的情况下,结果查询将是:

 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 

请注意,列别名是强制性的,否则PostgreSQL会抱怨列名不明确。

对于那些实际想要join的人,你也可以使用:

 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'; 

如果需要,可以在等号右边的SET部分使用a_alias。 等号左边的字段不需要表引用,因为它们被视为来自原始“a”表。

开始了:

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

简单,因为我可以做到。 多谢你们!

也可以这样做:

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

但是,您已经有了两次车辆表,并且只允许别名一次,而且不能在“设置”部分使用别名。

这是一个简单的SQL,它使用Name中的Middle_Name字段更新Name3表上的Mid_Name:

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