Hatena::ブログ(Diary)

Yet Another Hackadelic

2008-03-25 にぽながやまたんないと

SQLiteでForeign Key(もどき)を定義する

まぁ、デフォルトでは対応してないんですがTriggerを駆使して実現した人が居るみたいです。

まぁINSERTとかの時に参照してるカラムに該当してる値が無いとRAISE()するようなTriggerを定義する、、、みたいなノリですね。

CREATE TABLE User (
	user_seq INTEGER PRIMARY KEY,
	user_id TEXT,
	password_digest TEXT,
	created_on DATETIME DEFAULT current_date,
	updated_on DATETIME DEFAULT current_date
);

CREATE TABLE Profile (
	user_seq INTEGER PRIMARY KEY CONSTRAINT fk_user_seq REFERENCES User(user_seq),
	name TEXT,
	nickname TEXT,
	created_on DATETIME DEFAULT current_date,
	updated_on DATETIME DEFAULT current_date
);

こんな適当なテーブルだとすると、

CREATE TRIGGER fki_Profile_user_seq_User_user_seq
BEFORE INSERT ON [Profile]
FOR EACH ROW BEGIN
  SELECT RAISE(ROLLBACK, 'insert on table "Profile" violates foreign key constraint "fki_Profile_user_seq_User_user_seq"')
  WHERE NEW.user_seq IS NOT NULL AND (SELECT user_seq FROM User WHERE user_seq = NEW.user_seq) IS NULL;
END;

CREATE TRIGGER fku_Profile_user_seq_User_user_seq
BEFORE UPDATE ON [Profile]
FOR EACH ROW BEGIN
    SELECT RAISE(ROLLBACK, 'update on table "Profile" violates foreign key constraint "fku_Profile_user_seq_User_user_seq"')
      WHERE NEW.user_seq IS NOT NULL AND (SELECT user_seq FROM User WHERE user_seq = NEW.user_seq) IS NULL;
END;

CREATE TRIGGER fkd_Profile_user_seq_User_user_seq
BEFORE DELETE ON User
FOR EACH ROW BEGIN
  SELECT RAISE(ROLLBACK, 'delete on table "User" violates foreign key constraint "fkd_Profile_user_seq_User_user_seq"')
  WHERE (SELECT user_seq FROM Profile WHERE user_seq = OLD.user_seq) IS NOT NULL;
END;

こんなTriggerが必要です。

最もこれは書くのは面倒なので、ジェネレータもあるみたいです。

まぁ、Mozilla拡張とかでどうしても整合性取らなきゃダメなデータとか、そういう場合には使えるかもしれません。(気休め的な意味で)