MySQL でユニーク制約と論理削除を同時に実現する方法
はじめに
MySQL でユニーク制約と論理削除を同時に実現する方法。
TL;DR
- Generated Column を使う
- MySQL 5.7 以降であれば利用可能
- 別カラムを参照して値を切替可能
status = 1
なら'hoge'
,status = 2
なら'fuga'
みたいにできる
- Generated Column に対してユニーク制約を設定
目次
環境・条件
1 | mysql> status; |
詳細
参考:
- MySQL5.7以降で条件付きのユニーク制約をかけるためのベストプラクティス - Qiita
- MySQL :: MySQL 5.7 Reference Manual :: 13.1.18.7 CREATE TABLE and Generated Columns
MySQL 5.7 以降で使用可能な Generated Column を使う。
Generated Column を使うと status = 1
なら 'hoge'
, status = 2
なら 'fuga'
みたいに、他カラムを参照して動的に値を設定することが可能。かつ、Generated Column に対してユニーク制約を設定することもできる。
新規テーブル作成
email
: メールアドレスdiscarded_at
: 論理削除日時active_email
: 有効なメールアドレス(Generated Column)- ユニーク制約
1 | mysql> CREATE TABLE `my_users` ( |
カラム追加
email
はすでに存在する前提で、discarded_at
と active_email
, およびユニーク制約を追加する。
1 | mysql> ALTER TABLE `my_users` |
検証結果
hoge@fuga.com
のユーザーを登録。論理削除されてないので active_email
にそのまま反映される。
1 | mysql> INSERT INTO `my_users` (`email`) VALUES ('hoge@fuga.com'); |
もう一度 hoge@fuga.com
のユーザーを登録しようとするとユニーク制約でエラー。
1 | mysql> INSERT INTO `my_users` (`email`) VALUES ('hoge@fuga.com'); |
論理削除(discarded_at
を設定)すると、active_email
が NULL
になる。
1 | mysql> UPDATE `my_users` SET `discarded_at` = NOW() WHERE `id` = 1; |
この状態であれば hoge@fuga.com
のユーザーを登録できる。
1 | mysql> INSERT INTO `my_users` (`email`) VALUES ('hoge@fuga.com'); |
まとめ
- Generated Column を使う
- MySQL 5.7 以降であれば利用可能
- 別カラムを参照して値を切替可能
status = 1
なら'hoge'
,status = 2
なら'fuga'
みたいにできる
- Generated Column に対してユニーク制約を設定
参考文献
- MySQL :: MySQL 5.7 Reference Manual :: 13.1.18.7 CREATE TABLE and Generated Columns
- MySQL5.7以降で条件付きのユニーク制約をかけるためのベストプラクティス - Qiita
- 論理削除と一意性制約を両立させる方法・DB製品別 - Qiita
- 論理削除とユニークキー制約の両立 - Qiita
関連記事
- Rails で既存の DB を利用するアプリケーションの作成方法(DB 参照のみ)
- Rails で Devise と論理削除を両立する方法
- MySQL で DB をリネームする(複製(dump & load), テーブルを移動)
- Python で MySQL の操作が可能な ORM peewee
- MySQL で良く使う Tips
- JavaScript で URL のクエリパラメータを操作する方法
- jQuery Select2 で、初期値の設定と選択状態のクリア
- axios で添付ファイルありのリクエスト(multipart/form-data の POST)