2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

重複しているデータがあればINSERTをさせないようにする[MySQL, Go]

Posted at

データベースのレコードの挿入を自動で行うプログラムを作っていた際に、同じデータがあったら挿入させないようにするにはどうしたらいいのかわからなかったので調べて実装してみました。

コード

実際に実行するSQLクエリは下のようになっています。

INSERT INTO musics (music_name, composer,createdAt,updatedAt) 
SELECT ?,?,?,? WHERE NOT EXISTS (SELECT 1 FROM musics WHERE music_name = ?, AND composer = ?)

これはサブクエリで同じデータがないか確認し、存在しなければ実行するように条件分岐させています。

サブクエリ

サブクエリとは,sqlクエリの中にsqlクエリを書くことを言います。
上のクエリでは、WHERE文以降にある()で囲まれている部分がそれに該当します。

上のクエリにおけるサブクエリ内では、SELECT 1と書かれている部分があると思います。

これは、実際には以下のように動作します。

mysql> SELECT 1 FROM musics;
+---+
| 1 |
+---+
| 1 |
| 1 |
| 1 |
| 1 |
| 1 |
| 1 |
| 1 |
| 1 |
| 1 |
| 1 |
| 1 |
| 1 |
| 1 |
| 1 |
+---+
14 rows in set (0.00 sec)

このようにカラムに1を指定すると、レコードの件数分1が返されることになります。

SELECT * よりも早いという話がありますが、結果はわからないです

それをWHERE文で指定して件数分、1を表示させています。

加えて、WHERE NOT EXIST文で件数が0かどうかを調べています。
件数が0であると存在するものがないということでTrueとなり、INSERTが実行できます。件数が0より上であると存在するものがあるということでFalseとなり挿入することができません。

また、挿入の際にVALUESではなく、SELECTするのは条件付き挿入を行っているためです。

今回、このクエリをGoで行ったのですが、実際に使ったコードは下のようになっています。

import (
	"context"
	"database/sql"
	_ "github.com/go-sql-driver/mysql"
 )
 
func (m *MusicRepository) Register(ctx context.Context, music model.Music) error {
	query := `INSERT INTO musics (music_name, composer,createdAt,updatedAt) 
SELECT ?,?,?,? WHERE NOT EXISTS (SELECT 1 FROM musics WHERE music_name = ?, AND composer = ?)`

	_, err := m.db.ExecContext(ctx, query, music.MusicName, music.Composer, time.Now(), time.Now(), music.MusicName, music.Composer)

	if err != nil {
		//log.Fatal("database can't insert music", err)
		return fmt.Errorf("Error register music :%s", err)
	}

	return nil
}

?ってなんだと思われる方がいるかもしれませんが、?の部分はプレースホルダーで、後から数値を代入できるようにしています。
そのクエリをExecContextメソッドで実行しています。

ぜひお役に立てば嬉しいです。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?