別のテーブルのすべての列を更新する


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更新する必要があるからです。ロックをできるだけ少なくする必要があり、整合性を維持する必要があります。「削除してから挿入」が良い選択肢かどうかわかりませんか?tableAtableBtableAtableA


1
私はあなたの2番目のコードでテストしました、それは動作します!:次の2つのトピック見直すべきdba.stackexchange.com/questions/58371/...dba.stackexchange.com/questions/59458/...
ルアンフイン

回答:


12

行全体を一度に更新できる構文バリアントはありません。ただし、これまでの形式よりも短い形式があります。

また、実際にはすべての列を更新する必要はありません。WHEREid の条件は、id変更されないままにするために少なくとも1つの列()を固定します。しかし、それはほんのちょっとしたことです。

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

この関連する回答の詳細:
すべての列の一括更新

DELETE / INSERT

内部的には、PostgresMVCCモデルにより、すべてがUPDATEとにかく効果的に新しい行を挿入し、古い行を古いものとしてマークします。だから、カーテンの後ろの間に大きな違いはないUPDATEDELETEプラスINSERT。ルートに有利ないくつかの詳細
があります: UPDATE

  • ホットアップデート。
  • TOASTテーブル:大きな列がある場合、コンテンツが保存される可能性があります。TOASTテーブルの「行外」で、トーストされた列が変更されない場合、新しい行バージョンはTOASTテーブルの同じ行にリンクできます。
  • インデックスのメンテナンスは、更新の方が安くなる場合があります。

それ以外の場合、ロックはほぼ同じである必要があります。いずれにしても、影響を受ける行に排他ロックが必要です。早くしてください。
大量の行を処理していて、一貫した状態(すべての行またはなし)が必要ない場合は、操作を複数のバッチに分割できます。(個別のトランザクション!)合計コストは増加しますが、行ごとのロック時間は短くなります。


3
DELETE / INSERTまた、の効果とは異なる、または単に異なる(カスケードまたはトリガー)効果がある場合がありUPDATEます。
ypercubeᵀᴹ

正しいのですが、table_aのエイリアス部分を更新する必要があります。table_a(更新されたテーブル)はエイリアスを取得できません。
ちょうど別のコード恋人
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.