PostgreSQL 中具有多个连接的 UPDATE 语句
Posted
技术标签:
【中文标题】PostgreSQL 中具有多个连接的 UPDATE 语句【英文标题】:UPDATE statement with multiple joins in PostgreSQL 【发布时间】:2015-11-29 21:57:42 【问题描述】:我正在尝试更新一个名为 incode_warrants
的表,并将 warn_docket_no
从 incode_violations
表中设置为 viol_docket_no
。
我在 Postgres 9.3 中有以下 SQL 查询,但是当它触发时出现以下错误:
Error : ERROR: relation "iw" does not exist LINE 1: update iw
我更像是一个 Active Record 人,所以我的原始 SQL 技能严重缺乏。我想知道是否有人可以帮助我指出正确的方向,了解如何正确进行此查询。
update iw
set iw.warn_docket_no = iv.viol_docket_no
from incode_warrants as iw
INNER JOIN incode_warrantvs as iwvs
on iw.warn_rid = iwvs.warnv_rid
INNER JOIN incode_violations as iv
ON iv.viol_citation_no = iwvs.warnv_citation_no and iv.viol_viol_no = iwvs.warnv_viol_no
【问题讨论】:
【参考方案1】:这是我的代码,我在 a 和之后生成我的加入和附件,与我的可更新表和在我比较我的身份的地方,对不起我的英语
update cs_ticket ct
set site_name = a.name
from (
select ct.id, cs."name"
from cs_ticket ct
inner join cs_net_segment cns
on ct.affected_ip like cns.ip || '.%'
and end_date is null
inner join cs_site cs
on cs.id = cns.site_id)a
where ct.id = a.id;
【讨论】:
【参考方案2】:UPDATE incode_warrants iw
SET warn_docket_no = iv.viol_docket_no
FROM incode_warrantvs AS iwvs, incode_violations AS iv
WHERE iv.viol_citation_no = iwvs.warnv_citation_no AND
iv.viol_viol_no = iwvs.warnv_viol_no AND
iw.warn_rid = iwvs.warnv_rid;
【讨论】:
【参考方案3】:与 Postgres 中的有效 UPDATE
语句相同:
UPDATE incode_warrants iw
SET warn_docket_no = iv.viol_docket_no
FROM incode_warrantvs iwvs
JOIN incode_violations iv ON iv.viol_citation_no = iwvs.warnv_citation_no
AND iv.viol_viol_no = iwvs.warnv_viol_no
WHERE iw.warn_rid = iwvs.warnv_rid;
-- AND iw.warn_docket_no IS DISTINCT FROM iv.viol_docket_no -- see below
您不能只使用FROM
子句中的表别名作为UPDATE
子句中的目标表。要更新的(一个!)表紧跟在 UPDATE
关键字之后(如果我们忽略两者之间可能的 ONLY
关键字)。如果需要,您可以在此处添加别名。这是您的错误消息的直接原因,但还有更多。
要更新的列总是来自一个要更新的表,不能是表限定的。
您不需要在FROM
子句中重复目标表 - 像这样的特殊情况除外:
此可选添加可以通过抑制不改变任何内容的更新来避免无意义的成本:
AND iw.warn_docket_no IS DISTINCT FROM iv.viol_docket_no
见:
How do I (or can I) SELECT DISTINCT on multiple columns?More in the excellent manual on UPDATE
.
【讨论】:
很好的答案,感谢您的帮助和专业知识。我一定会阅读手册并提高我的技术! 如果您不介意,我确实有一个问题。我试图让这个更新语句在 MASSIVE 400 LOC 存储过程中触发。我已经将它注入到 SP 中,并设置了一个 Raise 信息来记录它何时触发,但在运行存储过程时它永远不会触发。自行运行更新工作正常。我应该创建一个新问题来解决这个问题吗? @shakycode:是的,一个包含所有必要细节的新问题是正确的举措。评论不是地方。您可以随时链接到这个以获取上下文。 会的!我需要以某种方式匿名存储过程,因为它具有专有的模式数据。我很快就会发布。再次感谢您的帮助,欧文!【参考方案4】:你更新一个表,而不是加入
update incode_warrants ALIAS
set warn_docket_no = iv.viol_docket_no
from incode_warrantvs as iw
...
【讨论】:
您不能在 Postgres 中对UPDATE
语句的目标列进行表限定。
@ErwinBrandstetter 感谢您的评论。我修复它。但我的回答只是解决了一个问题,在看到你的回答后意识到这不是一个完整的答案。【参考方案5】:
您的查询应如下所示:
UPDATE incode_warrants
SET warn_docket_no = incode_violations.viol_docket_no
FROM incode_violations
WHERE incode_violations.viol_citation_no = incode_warrants.warnv_citation_no
AND incode_violations.viol_viol_no = incode_warrants.warnv_viol_no;
您不需要任何其他加入。使用此查询,您只需使用另一个表中的列中的值更新一个表中的列。当然,只有在WHERE
条件为真时才会更新。
【讨论】:
感谢您的快速回答。当我运行它时,我得到了这个:Error : ERROR: column incode_warrants.warnv_citation_no does not exist LINE 4: WHERE incode_violations.viol_citation_no = incode_warrants.w...
你能用模式更新你的问题吗?我不敲你的桌子是什么样子的。需要更多解释。
您可能忽略了 incode_warrants
和 incode_warrantvs
是两个不同的表 - 当然,除非这是问题中的拼写错误。
正如 Erwin 提到的,这个解决方案缺少 incode_warrantvs
这就是我投反对票的原因。以上是关于PostgreSQL 中具有多个连接的 UPDATE 语句的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 PostgreSQL 中的变量创建具有内部连接的视图?
PostgreSQL 中具有特定模式的 Linq 和实体迁移