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

参考: