更新另一个表中的所有列


13

我需要从另一个表更新一个表,并且需要更新所有列。除了列出SET子句中的每一列之外,还有没有办法一次更新所有列?像这样:

update tableA
set * = tableB.*
from tableB where tableA.id = tableB.id

我在psql中尝试过,它不起作用。我必须像这样列出每一列:

update tableA
set c1 = tableB.c1, c2 = tableB.c2, ...
from tableB where tableA.id = tableB.id

tableB被创建使用create .. like tableA。因此,它们基本上是相同的。我这样做的原因是,我需要将.csv数据加载到临时表中tableB,然后tableA根据中的新数据进行更新tableBtableA需要尽可能少地锁定,并且tableA需要保持完整性。我不确定“先删除然后插入”是否是一个好选择?


1
我测试了您的第二个代码,它可以正常工作!:您应该检查两个主题dba.stackexchange.com/questions/58371/...dba.stackexchange.com/questions/59458/...
六安黄长发

Answers:


12

没有语法变种,它允许您一次更新整行。但是,它的形式比到目前为止的要短。

另外,您实际上并不想更新所有列。WHEREid上的条件将至少一列(id)固定以保持不变。但这只是挑剔。

UPDATE table_a a
SET    (  c1,   c2, ...)
     = (b.c1, b.c2, ...)
FROM   table_b b
WHERE  a.id = b.id;

此相关答案中的更多详细信息:
所有列的批量更新

DELETE / INSERT

在内部,由于PostgresMVCC模型,UPDATE无论如何,每个行都会有效地插入新行,并将旧行标记为过时。所以,窗帘后面没有太大的区别UPDATE,并DELETEINSERT
一些有利于该UPDATE路线的细节:

  • 热更新。
  • TOAST表:如果列很大,则可能会存储内容。TOAST表中的“行外”和新行版本可以链接到TOAST表中的同一行(如果保留的列保持不变)。
  • 索引维护更新可能会便宜一些。

否则,锁定应大致相同。无论哪种方式,您都需要对受影响的行具有排他锁。只要快点。
如果您要处理的行数很大,并且不需要一致的状态(所有行或无行),则可以将操作分为多个批处理。(单独的事务!)增加了总成本,但使每行的锁定时间更短。


3
DELETE / INSERT可能还具有与相比不想要的效果或只是不同(层叠或触发)效果UPDATE
ypercubeᵀᴹ

正确,但是您应该更新table_a的别名部分。table_a(已更新的表)无法获取别名。
Just Just Code Lover
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.