如何在PostgreSQL中进行更新+加入?

时间:2011-10-23 22:09:23

标签: postgresql syntax

基本上,我想这样做:

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中写这个?

9 个答案:

答案 0 :(得分:677)

UPDATE syntax是:

[ WITH [ RECURSIVE ] with_query [, ...] ]
UPDATE [ ONLY ] table [ [ AS ] alias ]
    SET { column = { expression | DEFAULT } |
          ( column [, ...] ) = ( { expression | DEFAULT } [, ...] ) } [, ...]
    [ FROM from_list ]
    [ WHERE condition | WHERE CURRENT OF cursor_name ]
    [ RETURNING * | 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 

答案 1 :(得分:113)

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

任务:正确的信息,即abiturients(即将离开中学的学生)早些时候向大学提交申请,而不是他们获得学校证书(是的,他们获得的证书早于他们颁发的证书(按照指定的证书日期)。所以,我们将增加申请提交日期以适应证书签发日期。

因此。下一个类似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

正如您所看到的,原始子查询JOIN的{​​{1}}子句已成为ON条件之一,由WHERE与其他条件相结合,已被移动来自子查询,没有任何变化。并且不再需要AND表自身(就像在子查询中一样)。

答案 2 :(得分:104)

Mark Byers的答案在这种情况下是最佳的。 虽然在更复杂的情况下,您可以使用返回rowid和计算值的select查询,并将其附加到更新查询,如下所示:

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

此方法允许您开发和测试您的选择查询,并分两步将其转换为更新查询。

因此,在您的情况下,结果查询将是:

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会抱怨列名的含糊不清。

答案 3 :(得分:48)

对于那些真正想要做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' 
AND a.id = a_alias.id;

如果需要,您可以在等号右侧的SET部分使用a_alias。 等号左侧的字段不需要表格参考,因为它们被认为来自原始的&#34; a&#34;表

答案 4 :(得分:5)

对于那些想要执行JOIN的用户,只更新您的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' 
AND a.id = a_alias.id
--the below line is critical for updating ONLY joined rows
AND a.pk_id = a_alias.pk_id;

上面已经提到了这一点,但仅是通过注释。由于获得正确结果并发布有效的新答案至关重要,因此很重要

答案 5 :(得分:4)

我们走了:

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

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

也可以这样做:

-- Doesn't work apparently
update vehicles_vehicle 
set price=s.price_per_vehicle
from vehicles_vehicle v
join shipments_shipment s on v.shipment_id=s.id;

但是那时你已经在那里拿到了两次车辆表,并且你只允许别名一次,而且你不能在&#34;中使用别名。设定&#34;部分。

答案 6 :(得分:0)

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

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

答案 7 :(得分:0)

下面的链接提供了一个示例,可以解决并帮助您更好地了解如何将updatejoin与postgres一起使用。

UPDATE product
SET net_price = price - price * discount
FROM
product_segment
WHERE
product.segment_id = product_segment.id;

请参阅:http://www.postgresqltutorial.com/postgresql-update-join/

答案 8 :(得分:0)

第一个表名称:tbl_table1(tab1)。 第二个表名称:tbl_table2(tab2)。

将tbl_table1的ac_status列设置为“ INACTIVE”

update common.tbl_table1 as tab1
set ac_status= 'INACTIVE' --tbl_table1's "ac_status"
from common.tbl_table2 as tab2
where tab1.ref_id= '1111111' 
and tab2.rel_type= 'CUSTOMER';