更新另一个表中的所有列

odi*_*tla 13 postgresql update

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

update tableA
set * = tableB.*
from tableB where tableA.id = tableB.id
Run Code Online (Sandbox Code Playgroud)

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

update tableA
set c1 = tableB.c1, c2 = tableB.c2, ...
from tableB where tableA.id = tableB.id
Run Code Online (Sandbox Code Playgroud)

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

Erw*_*ter 12

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

此外,您实际上并不想更新所有列。WHEREid 上的条件至少固定一列 ( id) 以保持不变。但这只是吹毛求疵。

UPDATE table_a a
SET    (  c1,   c2, ...)
     = (b.c1, b.c2, ...)
FROM   table_b b
WHERE  a.id = b.id;
Run Code Online (Sandbox Code Playgroud)

此相关答案中的更多详细信息:
Bulk update of all columns

DELETE / INSERT

在内部,由于PostgresMVCC 模型,UPDATE无论如何每个有效地插入一个新行并将旧的标记为过时。所以,在幕后UPDATEDELETEplus之间没有太大区别INSERT
一些细节有利于这UPDATE条路线:

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

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

  • `DELETE / INSERT` 也可能具有与 `UPDATE` 不同的(级联或触发)效果。 (3认同)