INSERT
すべての行を挿入するだけで、何もありません ただしでない限り、特別なことが起こります ある種の制約があります 重複/重複する値を禁止する(PRIMARY KEY
、UNIQUE
、CHECK
またはEXCLUDE
制約)-あなたはあなたの質問で言及しませんでした。しかし、それはおそらくあなたが心配していることです。
UNIQUE
を想定 または(col1,col2)
のPK制約 、教科書UPSERT
を扱っています 状況。ここで見つけるための多くの関連する質問と回答。
一般的に、 any 制約に違反すると、例外が発生します(plpgsqlなどの手続き型サーバー側言語で可能なようにサブトランザクションにトラップされない限り)ステートメントだけでなく、トランザクション全体もロールバックします。 。
同時書き込みなし
つまり、他のトランザクションが同時に同じテーブルに書き込もうとすることはありません。
-
WHERE NOT EXISTS ...
を使用してテーブルにすでに存在する行を除外します またはその他の適用可能な手法: -
他のテーブルに存在しない行を選択してください
-
また、内の重複を削除することを忘れないでください 挿入されたセットもありません セミアンチジョインによって除外される
WHERE NOT EXISTS ...
両方を同時に処理する1つの手法は、EXCEPT
です。 :
INSERT INTO tbl (col1, col2)
VALUES
(text 'v1', text 'v2') -- explicit type cast may be needed in 1st row
, ('v3', 'v4')
, ('v3', 'v4') -- beware of dupes in source
EXCEPT SELECT col1, col2 FROM tbl;
EXCEPT
キーワードALL
なし ソース内の重複する行を折ります。重複がないことがわかっている場合、または重複をサイレントに折りたたむ必要がない場合は、EXCEPT ALL
を使用してください (または他の手法の1つ)。参照:
- PostgreSQLでEXCEPT句を使用する
一般に、ターゲットテーブルが大きい場合 、WHERE NOT EXISTS
DISTINCT
と組み合わせて ソース上でおそらくより速くなります:
INSERT INTO tbl (col1, col2)
SELECT *
FROM (
SELECT DISTINCT *
FROM (
VALUES
(text 'v1', text'v2')
, ('v3', 'v4')
, ('v3', 'v4') -- dupes in source
) t(c1, c2)
) t
WHERE NOT EXISTS (
SELECT FROM tbl
WHERE col1 = t.c1 AND col2 = t.c2
);
重複が多数ある可能性がある場合は、最初にソースでそれらを折りたたむことをお勧めします。それ以外の場合は、1つのサブクエリを使用します。
関連:
- 他のテーブルに存在しない行を選択します
同時書き込みあり
PostgresのUPSERT
を使用する 実装INSERT ... ON CONFLICT ...
Postgres 9.5 以降:
INSERT INTO tbl (col1,col2)
SELECT DISTINCT * -- still can't insert the same row more than once
FROM (
VALUES
(text 'v1', text 'v2')
, ('v3','v4')
, ('v3','v4') -- you still need to fold dupes in source!
) t(c1, c2)
ON CONFLICT DO NOTHING; -- ignores rows with *any* conflict!
さらに読む:
- PostgreSQLでONCONFLICTを使用してRETURNINGを使用するにはどうすればよいですか?
- 外部キーを含む行を挿入するにはどうすればよいですか?
ドキュメント:
- マニュアル
- コミットページ
- PostgresWikiページ
UPSERT
に対するCraigのリファレンスアンサー 問題:
- PostgreSQLでUPSERT(MERGE、INSERT ... ON DUPLICATE UPDATE)する方法