PostgreSQL INSERT ON CONFLICT UPDATE(upsert)はすべての除外値を使用します


142

行をアップサートし(PostgreSQL> = 9.5)、可能なINSERTを可能なUPDATEとまったく同じにしたい場合は、次のように記述できます。

INSERT INTO tablename (id, username, password, level, email) 
                VALUES (1, 'John', 'qwerty', 5, 'john@mail.com') 
ON CONFLICT (id) DO UPDATE SET 
  id=EXCLUDED.id, username=EXCLUDED.username,
  password=EXCLUDED.password, level=EXCLUDED.level,email=EXCLUDED.email

もっと短い方法はありますか?ただ言うと、すべてのEXCLUDE値を使用します。

SQLiteで私は以前使用していました:

INSERT OR REPLACE INTO tablename (id, user, password, level, email) 
                        VALUES (1, 'John', 'qwerty', 5, 'john@mail.com')

43
本当の答えではありませんが、少し短い表記法を使用できます。 INSERT INTO tablename (id, username, password, level, email) VALUES (1, 'John', 'qwerty', 5, 'john@mail.com') ON CONFLICT (id) DO UPDATE SET (username, password, level, email) = (EXCLUDED.username, EXCLUDED.password, EXCLUDED.level, EXCLUDED.email).ほとんど同じですが、列リストをコピー/貼り付け/管理するのは簡単です
foal

別のオプションは使用jsonb列にあり、その方法は、あなたが列を心配する必要はありません
jの意志

回答:


162

Postgresはに相当するものを実装していませんINSERT OR REPLACEON CONFLICTドキュメントから(私の強調):

DO NOTHING、または競合が発生した場合に実行されるUPDATEアクションの正確な詳細を指定するDO UPDATE句のいずれかです。

置換の省略形は提供されませんがON CONFLICT DO UPDATE、既存のデータに基づいて新しい値を設定できるため、より一般的に適用されます。例えば:

INSERT INTO users (id, level)
VALUES (1, 0)
ON CONFLICT (id) DO UPDATE
SET level = users.level + 1;

3
注意点として、「更新時」は、SQL標準の「マージ」と意味的に同じではありませんが、通常は同じ場所で使用できます。「競合する更新」が実行されると予想したケースがありましたが、挿入の正確な問題が原因で、更新(破損したレコードが修復されたはず)が起動しませんでした。
pojo-guy

2
「しかし、挿入の正確な問題は更新の原因にはなりませんでした」に拡張できますか?
MrR

@ pojo-guy-MrRからの質問を見たとは思いません-「挿入の正確な問題が原因で更新が発生しなかった」と展開できますか?
Randall

postgresqlのupdateでinsert ...を使用しようとすると、特定の状況下ではマージとは結果が異なります。私が遭遇したケースはかなりあいまいで具体的でしたが、それは再現可能でした。数か月経ちましたので、これ以上お伝えすることはできません。
pojo-guy

おそらくそれは競合ではなく、別のエラーです(フィールドタイプエラーなど)。
MrR
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.