基本上,我想这样做:
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 中编写这个?
vehicles_*
表和几个 shipments_*
表。
[ 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
Mark Byers 的答案在这种情况下是最优的。尽管在更复杂的情况下,您可以使用返回 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 table1
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 会抱怨列名的歧义。
让我通过我的例子再解释一下。
任务:正确的信息,其中学生(即将离开中学的学生)比他们获得学校证书更早提交申请到大学(是的,他们获得证书的时间早于他们颁发的证书(在指定的证书日期之前)。所以,我们将增加申请提交日期以适应证书颁发日期。
因此。下一个类似 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
的 ON
子句已成为 WHERE
条件之一,由 AND
与其他条件结合,这些条件已从子查询中移出而没有更改。并且不再需要 JOIN
自己的表(就像在子查询中一样)。
FROM
列表中JOIN
它:FROM abiturients b JOIN addresses c ON c.abiturient_id = b.id
from_list
子句(这是 PostgreSQL 对 SQL 的扩展)中使用它。此外,请参阅您提供的链接上有关加入表格注意事项的说明。
对于那些真正想要做 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。等号左侧的字段不需要表引用,因为它们被认为来自原始“a”表。
对于那些想要进行仅更新您的联接返回的行的联接的人,请使用:
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;
上面提到了这一点,但仅通过评论..因为发布有效的新答案对于获得正确结果至关重要
AND a.pk_id = a_alias.pk_id
,这里没有交叉连接,答案是有效。本评论的链接和引用只会让读者陷入疯狂的追逐,完全浪费他们的时间,试图理解你所指的内容。
开始了:
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;
但是你有两次车辆表在那里,你只能给它起别名,你不能在“设置”部分使用别名。
join
没有限制它吗?
要为上述所有出色答案添加一些非常重要的内容,当您想要更新 join-table
时,您可能会遇到 2 个问题:
您不能使用要更新的表来加入另一个表
Postgres 希望在 JOIN 之后有一个 ON 子句,因此您不能只使用 where 子句。
这意味着基本上,以下查询无效:
UPDATE join_a_b
SET count = 10
FROM a
JOIN b on b.id = join_a_b.b_id -- Not valid since join_a_b is used here
WHERE a.id = join_a_b.a_id
AND a.name = 'A'
AND b.name = 'B'
UPDATE join_a_b
SET count = 10
FROM a
JOIN b -- Not valid since there is no ON clause
WHERE a.id = join_a_b.a_id
AND b.id = join_a_b.b_id
a.name = 'A'
AND b.name = 'B'
相反,您必须像这样使用 FROM
子句中的所有表:
UPDATE join_a_b
SET count = 10
FROM a, b
WHERE a.id = join_a_b.a_id
AND b.id = join_a_b.b_id
AND a.name = 'A'
AND b.name = 'B'
对某些人来说这可能很简单,但我被困在这个问题上,想知道发生了什么,所以希望它能帮助其他人。
下面是一个简单的 SQL,它使用 Name 中的 Middle_Name 字段更新 Name3 表上的 Mid_Name:
update name3
set mid_name = name.middle_name
from name
where name3.person_id = name.person_id;
下面的链接有一个示例,可以解决并帮助更好地理解如何将 update
和 join
与 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/
第一个表名称: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';
select
的相同连接也不会仅通过添加set
短语来update
:( 仍然 - 对于 sql 的新手来说,这种语法可能更容易掌握。