PL/SQLでデータをINSERTまたはUPDATEする処理は、業務システムで頻繁に登場します。例えば「データが存在すれば更新し、なければ新規挿入する」というロジックは、通称「UPSERT(アップサート)」と呼ばれます。
このような処理を簡潔かつ効率よく記述できるのが、OracleのMERGE文です。本記事では、MERGE文の基本構文と応用例、パフォーマンス面や注意点について解説します。
MERGE文とは?
MERGE文は、1つのSQLでUPDATEまたはINSERTのいずれかを実行できる構文です。複数のSQL文を書く必要がないため、ロック競合や二重登録を防ぎつつ、シンプルに記述できます。
基本構文
MERGE INTO target_table tgt
USING (SELECT :id AS id, :name AS name FROM dual) src
ON (tgt.id = src.id)
WHEN MATCHED THEN
UPDATE SET tgt.name = src.name
WHEN NOT MATCHED THEN
INSERT (id, name) VALUES (src.id, src.name);
この構文は以下の処理を意味します:
- idが一致するレコードが
target_table
にあれば、name
を更新 - 一致しなければ新規に挿入
MERGE文のメリット
- 処理が1文で完結するため、トランザクション管理がしやすい
- ロック競合や重複INSERTのリスクが少ない
- IF文による分岐処理が不要で、可読性が高い
- パフォーマンスが高い(UPDATE対象とINSERT対象を一括判定)
応用例:複数レコードを一括アップサート
複数行を一括でアップサートする場合は、サブクエリや一時テーブルを使ってデータを渡すことができます。
MERGE INTO employees tgt
USING (
SELECT 1001 AS emp_id, '田中' AS emp_name FROM dual
UNION ALL
SELECT 1002, '佐藤' FROM dual
) src
ON (tgt.emp_id = src.emp_id)
WHEN MATCHED THEN
UPDATE SET tgt.emp_name = src.emp_name
WHEN NOT MATCHED THEN
INSERT (emp_id, emp_name) VALUES (src.emp_id, src.emp_name);
このようにして、データの存在確認→更新または挿入という流れを1文で効率的に処理できます。
MERGE文を使う際の注意点
- ON句の条件が適切でないと、誤ったレコードが更新されるリスクがある
- NOT MATCHED BY SOURCEによる削除処理など、書き方によっては全削除になる危険がある
- 対象テーブルにユニーク制約がある場合、MERGE内でのINSERTが失敗する可能性がある
特にON条件の設定ミスは重大なデータ事故につながるため、業務要件に即した厳密な条件設計が求められます。
MERGE文とトランザクション管理
MERGE文は1文で完結するため、トランザクションの境界を明確にできるのも利点の一つです。例えば複数のMERGEを行う場合でも、BEGIN ~ COMMIT
で囲むことで一括制御が可能です。
BEGIN
-- MERGE文1
-- MERGE文2
COMMIT;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
RAISE;
END;
まとめ:MERGE文はUPSERTの最適解
UPSERT処理が必要な場面では、MERGE文を活用することでSQLの記述量を減らし、トランザクション管理やパフォーマンスも向上します。
ただし、ON条件の精査と更新/挿入対象列の設計には十分な注意が必要です。誤ったデータ更新や意図しない重複を防ぐためにも、事前に検証環境でしっかりとテストを行いましょう。
MERGE文を使いこなせば、PL/SQLにおけるデータ整合性の維持とコードの簡素化を同時に実現できます。