SQLiteで外部キー制約を使えるようにする
いまさらですが、SQLiteの3.6.19から外部キーが使えるようになったそうです。
ただ、互換性の都合でデフォルトでは外部キー制約は無効になっているので、DBにつなぐ度に
PRAGMA foreign_keys = ON;
を実行してやる必要があります。
(将来的にデフォルトで有効にするかもしれないけれど、それを前提にするな、だそうです)
Windows用Ver3.7.3 でその動作を確認してみると、
C:\>sqlite3 test.db SQLite version 3.7.3 Enter ".help" for instructions Enter SQL statements terminated with a ";" sqlite> PRAGMA foreign_keys; 0
とデフォルトで無効です。
この状態で、次の外部キー制約を使ったSQLを食わせてみます。
BEGIN TRANSACTION; CREATE TABLE idmaster (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT); INSERT INTO idmaster VALUES (null, "A"); INSERT INTO idmaster VALUES (null, "B"); CREATE TABLE address (id INTEGER, address TEXT, FOREIGN KEY(id) REFERENCES idmaster(id)); INSERT INTO address VALUES (1, "addressA"); INSERT INTO address VALUES (2, "addressB"); INSERT INTO address VALUES (3, "addressC"); COMMIT;
そうするとなんのエラーも出ずに実行できてしまいます。
テーブルの中味を確認すると、、
sqlite> SELECT * FROM idmaster; 1|A 2|B sqlite> SELECT * FROM address; 1|addressA 2|addressB 3|addressC
このように、制約無視で走っちゃってます。
次に外部キー制約を有効にして同じ事をやってみます。
まずは外部キー制約を有効にしてやり、
sqlite> PRAGMA foreign_keys=ON; sqlite> PRAGMA foreign_keys; 1
そして同じSQLを食わすと、
sqlite> INSERT INTO address VALUES (3, "addressC"); Error: foreign key constraint failed
INSERT 時点で外部キー制約違反なエラーがでます。
そしてテーブル内容も次の通り、制約に沿ったものになります。めでたしめでたし。
sqlite> SELECT * FROM idmaster; 1|A 2|B sqlite> SELECT * FROM address; 1|addressA 2|addressB
参考: