PostgreSQLを使ってデータを登録していると、「すでに存在している行を重複してINSERTしてしまった」という経験はありませんか?
特に、IDやメールアドレスなど、一意であるべき情報が重複すると、システムの不具合やデータの不整合につながる恐れがあります。
そこで本記事では、「すでに存在する行がある場合にはINSERTをスキップする」方法について、実践的なSQLの書き方を交えてわかりやすく解説します。
PostgreSQLには、NOT EXISTS
やON CONFLICT
といった便利な構文が用意されており、シンプルかつ安全に重複を防止する方法を実現できます。
SQL初心者の方や、データベースを扱うエンジニアの方にとって、すぐに業務に役立つ内容となっていますので、ぜひ参考にしてください。
方法1:INSERT … SELECT + NOT EXISTS
まずご紹介するのは、PostgreSQLに限らず多くのRDBMSで利用できる基本的な方法、INSERT ... SELECT
文と NOT EXISTS
を組み合わせる手法です。
この方法では、指定した条件に一致する行がすでに存在しない場合のみINSERTすることができます。
INSERT INTO users (id, name)
SELECT 1, 'Alice'
WHERE NOT EXISTS (
SELECT 1 FROM users WHERE id = 1
);
ポイント
ON CONFLICT DO NOTHING(PostgreSQL特有)
PostgreSQLに限定されますが、よりシンプルに重複INSERTを防ぐことができる構文があります。
それが、ON CONFLICT DO NOTHING
です。
この構文は、INSERT時に一意制約(UNIQUEやPRIMARY KEY)に違反するデータがあった場合、何もせずにスキップするという動作をしてくれます。
INSERT INTO users (id, name)
VALUES (1, 'Alice')
ON CONFLICT (id) DO NOTHING;
前提条件:一意制約が必要
この構文を利用するには、対象列に対して一意制約(UNIQUE)またはPRIMARY KEYが設定されている必要があります。
ポイント
複数行のINSERT文も書ける
INSERT INTO users (id, name)
VALUES (1, 'Alice'), (2, 'Bob'), (3, 'Carol')
ON CONFLICT (id) DO NOTHING;
一意制約が必要となりますが、一括INSERTと重複回避を同時に実現できるのが大きな利点です。
まとめ
今回は、PostgreSQLで「存在しない行のみINSERTする方法」について、代表的な2つの手法をご紹介しました。
方法 | 特徴 | 向いているケース |
---|---|---|
INSERT ... SELECT ... WHERE NOT EXISTS | 柔軟な条件判定が可能。構文は少し冗長。 | 一意制約がない場合や、複雑な存在判定をしたいとき |
INSERT ... ON CONFLICT DO NOTHING | 非常に簡潔でスマート。PostgreSQL専用の構文。 | 一意制約があるシンプルなINSERT処理 |
どちらの方法も、重複によるエラーやデータ不整合を防ぐために非常に重要なテクニックです。
実際の開発や運用の現場では、「一意制約の有無」「登録条件の複雑さ」「処理件数」などに応じて、最適な方法を選び使い分けることがポイントとなります。
データベースは、正確で信頼性の高い情報を蓄積・活用するための基盤です。
そのためにも、「重複を防ぐINSERT処理」はぜひマスターしておきましょう。
コメント