【MySQL】重複がなければINSERTするSQL【キー制約不要】

MySQL

指定した列の値をキーにして重複チェックを行い、重複するレコードがなければINSERTし、あればINSERTしない、という処理のSQLを紹介します。

INSERT ON DUPLICATE KEY UPDATEREPLACE INTO も重複をチェックしたうえでINSERTを実行してくれますが、重複チェックに用いるのはPRIMARY KEY または UNIQUE インデックスが設定されている列を使って重複チェックを行います。

本記事で紹介する方法はPRIMARY KEY または UNIQUE インデックスが設定されていなくても、SQLの中で指定した列を使って重複チェックしてINSERTするか否か判定することができます。

本記事ではMySQLで操作するSQLを紹介しますが、SQLの体裁を少し変えれば他のデータベース用のSQLとして利用することもできると思います。

SQLの説明

まずは図を用いてSQLを説明します。

下記のようなデータ構成で、Item1列とItem2列の組み合わせが一致するレコードがあるかを基に重複チェックを行います。重複がなければINSERTし、重複があればINSERTしません。下記のデータ構成の場合は1行目のレコードはINSERTされず、2行目と3行目のレコードが挿入されることになります。

データ構成

SQLの処理の流れについて、まずINSERTするデータを基点にItem1、Item2をキーにLEFTJOINを行います。(結合先が見つからないということは同じデータが存在しないということになります。)

LEFT JOIN した結果イメージ

そしてWHERE句で結合先がNULLのデータをピックアップ及びINSERT処理に必要な列をピックアップしテーブルへINSERTを行います。(ここではid列はauto_incrementを指定しているのでINSERT対象列にしていません。)

イメージ

ちなみに、SELECTした結果をINSERTする構文は下記の記事で確認できます。

selectした結果をinsertする - Qiita
毎回忘れるのでメモ以下の書き方はNG(毎回やらかす)insert into table_name (col1, col2, ...)values (select col1, col2, ...…

SQLの紹介

上記で説明したサンプルの処理を行うSQLを紹介します。

ここで紹介するSQLをそのまま使用して動作確認したい場合、まずはテーブルの用意と既存データを用意する必要があります。下記はサンプルSQLを動かすためのテーブルと既存データを用意するためのSQLとなりますので必要に応じて使用してください。

CREATE TABLE IF NOT EXISTS `test` (	
  `id` int(11) NOT NULL AUTO_INCREMENT,	
  `Item1` varchar(50) NOT NULL,	
  `Item2` varchar(50) NOT NULL,	
  `Item3` varchar(50) NOT NULL,	
  PRIMARY KEY (`id`)	
);	
	
INSERT INTO `test` (`Item1`, `Item2`, `Item3`) VALUES ( '01', '01', '01');

そして下記のSQLが上記のサンプルで説明した仕様のSQLとなります。重複チェックに用いる列をLEFTJOINのON句で指定しています。チェックするデータをUNION句を使ってまとめていますが必ずしもUNION句を使う必要はありません。

INSERT INTO test (Item1, Item2, Item3)
SELECT
CheckData.Item1
,CheckData.Item2
,CheckData.Item3
FROM
(
SELECT "01" Item1, "01" Item2, "02" Item3
UNION 
SELECT "01" Item1, "02" Item2, "01" Item3
UNION 
SELECT "02" Item1, "01" Item2, "01" Item3
) CheckData
LEFT JOIN test AlreadyData ON
 CheckData.Item1 = AlreadyData.Item1 AND
 CheckData.Item2 = AlreadyData.Item2
WHERE AlreadyData.Item1 IS NULL

以上となります。参考になれば幸いです。

タイトルとURLをコピーしました