一意制約。
成果物
unique
制約
unique
制約を与えられた列は、そのテーブルがもつ全レコード内で一意の値を持つことが保証される。もし違反したらエラーになる。
SQLite3においてinteger primary key
との違いは、自動インクリメントされないこと。もっとも、integer primary key
以外のprimary key
は、インデックスを持ったunique
制約と同義である。
使いどころ
インデックスを持たせず一意にしたいとき。
一覧
unique
テーブル作成
0_0.sql
create table T(A text unique);
Error: near line 3: UNIQUE constraint failed: T.A
違反
0_1.sql
create table T(A text unique); insert into T values('A'); insert into T values('A');
Error: near line 3: UNIQUE constraint failed: T.A
unique on conflict ...
rollback
1_0.sql
create table T(A text unique on conflict rollback); insert into T values('A'); begin; insert into T values('B'); insert into T values('B'); insert into T values('C'); end; select * from T;
Error: near line 5: UNIQUE constraint failed: T.A Error: near line 6: cannot commit - no transaction is active A C
abort
1_1.sql
create table T(A text unique on conflict abort); insert into T values('A'); begin; insert into T values('B'); insert into T values('B'); insert into T values('C'); end; select * from T;
Error: near line 5: UNIQUE constraint failed: T.A A B C
fail
1_2.sql
create table T(A text unique on conflict fail); insert into T values('A'); begin; insert into T values('B'); insert into T values('B'); insert into T values('C'); end; select * from T;
Error: near line 5: UNIQUE constraint failed: T.A A B C
ignore
1_3.sql
create table T(A text unique on conflict ignore); insert into T values('A'); begin; insert into T values('B'); insert into T values('B'); insert into T values('C'); end; select * from T;
A B C
思うのだが、制約をつけておきながら制約を無視するとか、何の意味があるの? エラーを抑制したいなら最初から制約を付けなければいいと思うのだが。
replace
1_4.sql
create table T(A text unique on conflict replace); insert into T values('A'); begin; insert into T values('B'); insert into T values('B'); insert into T values('C'); end; select * from T;
A B C
置換後に一意でなかったらどうなるか。
1_4_0.sql
create table T(A integer primary key, B text unique on conflict replace); insert into T(A,B) values(1,'A'); begin; insert into T(A,B) values(2,'B'); insert into T(A,B) values(3,'A'); insert into T(A,B) values(4,'C'); end; select * from T;
2|B 3|A 4|C
なんと、主キー値が置き換えられた! これは危険すぎ……。もはやお前が主キー。
何が危険か。もしこの主キーが他のテーブルの外部キーの参照先として使われていたら、整合性が保てなくなってしまう。対策としてはトリガーを作ることが考えられる。主キーが変更されたとき、参照する側の値も一緒に変更するように。
対象環境
- Raspbierry pi 3 Model B+
- Raspbian stretch 9.0 2018-11-13
- bash 4.4.12(1)-release
- SQLite 3.29.0
- MeCab 0.996ユーザ辞書
$ uname -a Linux raspberrypi 4.19.42-v7+ #1218 SMP Tue May 14 00:48:17 BST 2019 armv7l GNU/Linux
前回まで
- SQLite3学習 俯瞰まとめ
- SQLite3学習 環境構築まとめ
- SQLite3学習 インタフェースまとめ(C言語、CLI、対話モード、Tcl...)
- SQLite3学習 ドットコマンドまとめ
- SQLite3学習 JSON拡張まとめ
- SQLite3学習 FTSまとめ(ICU, MeCab)
- SQLite3学習 再帰クエリ(WITH RECURSIVE)
- SQLite3学習 R-Treeモジュール
- SQLite3学習 Geopoly(2次元ベクタ画像の生成)
- SQLite3学習 拡張関数(generate_series)
- SQLite3学習 拡張ライブラリ数学関数(extension-functions.c)
- SQLite3学習 謎と名前
- SQL文の分類(DDL,DML,TCL,DCL)
- SQL構文 alter(rename)
- SQL構文 alter(add column)概要
- SQL構文 alter(add column)制約
- SQL構文 alter(add column)sqlite_master変更しても反映されない
- SQL構文 alter(add column)スキーマ再定義(テーブル再作成による定義変更)
- SQL構文 analyze
- SQL構文 attach/detach
- SQLite3構文 begin,end,commit,rollback,savepoint(deferred,immediate,exclusive)
- SQLite3構文 コメント
- SQLite3構文 create/drop
- SQLite3構文 index(create/drop)
- SQLite3構文 table(create/drop)
- SQLite3構文 列制約(default)
- SQLite3構文 列制約(collate)
- SQLite3構文 列制約(primary key)
- SQLite3構文 列制約(primary key)ベストプラクティス