RESTRICTは、参照された行の削除を防ぎます。 NO ACTIONは、制約のチェック時に参照行がまだ存在する場合、エラーが発生することを意味します。何も指定しない場合、これがデフォルトの動作です。 (これら2つの選択肢の本質的な違いは、NO ACTIONではチェックがトランザクションの後半まで延期されることができるのに対し、RESTRICTでは許可されない)ことです。
確認してみましょう。親テーブルと子テーブルを作成します。
CREATE TABLE parent (
id serial not null,
CONSTRAINT parent_pkey PRIMARY KEY (id)
);
CREATE TABLE child (
id serial not null,
parent_id serial not null,
CONSTRAINT child_pkey PRIMARY KEY (id),
CONSTRAINT parent_fk FOREIGN KEY (parent_id)
REFERENCES parent (id)
ON DELETE NO ACTION
ON UPDATE NO ACTION
);
一部のデータを入力します。
insert into parent values(1);
insert into child values(5, 1);
そして、テストはチェックを本当に延期します:
BEGIN;
delete from parent where id = 1; -- violates foreign key constraint, execution fails
delete from child where parent_id = 1;
COMMIT;
最初の削除の整合性は壊れましたが、2番目の後で復元されました。ただし、最初の削除時に実行が失敗します。
更新についても同じ:
BEGIN;
update parent set id = 2 where id = 1; -- same as above
update child set parent_id = 2 where parent_id = 1;
COMMIT;
削除の場合はステートメントをスワップして機能させることができますが、更新の場合は実行できません(両方の行を削除して新しいバージョンを挿入することで達成できます)。
多くのデータベースでは、RESTRICTとNO ACTIONの間に違いはありませんが、postgresはそれ以外のふりをします。それは(まだ)本当ですか?
違いは、制約をINITIALLY DEFERRED
またはINITIALLY IMMEDIATE
モードでDEFERRABLE
として定義した場合にのみ発生します。
SET CONSTRAINTS
を参照してください。