Oracle の参照整合性制約
テーブル間でデータの整合性を保つために、関連付けを行う参照整合性制約がある。
親テーブルに従属する子テーブルに定義されている参照列を外部キー(Foreign Key)という。
主キーを PK と省略して言うように、よく外部キーのことを FK とも言われる。
指定方法
子テーブルの関連データに対するオプションとして、
on delete cascade や on delete set null がある。
オプションの使い方を間違えると消失リスクもあるので、ご注意を。
on 句なし
参照している子テーブルの該当行がある場合、親テーブルの行を削除できない。
on delete cascade
親テーブルの行が削除される場合、参照している子テーブルの該当行も削除される。
on delete set null
親テーブルの行が削除される場合、参照している子テーブルの該当行は null に更新される。
検証データ
ここでは部門マスタ(bumon)に登録されている3部が廃止され、
所属社員は1部、2部に配属されることを想定している。
/* 部門マスタ */
create table bumon(
code char(2) primary key,
bname varchar2(10)
);
insert into bumon values('01', '1部');
insert into bumon values('02', '2部');
insert into bumon values('03', '3部');
commit;
/* 社員マスタ */
create table syain(
id char(5) primary key,
uname varchar2(10),
bcode char(2)
);
insert into syain values('10001', '社員1', '01');
insert into syain values('10002', '社員2', '01');
insert into syain values('10003', '社員3', '02');
insert into syain values('10004', '社員4', '02');
insert into syain values('10005', '社員5', '03');
insert into syain values('10006', '社員6', '03');
commit;
オプションによる違い
on 句なし
SQL> alter table syain add constraint fk foreign key (bcode) references bumon (code); 表が変更されました。
SQL> delete from bumon where code = '03'; ORA-02292: 整合性制約(HOGE.FK)に違反しました - 子レコードがあります
→ 従属する子レコード(ID:10005、10006)が存在するためエラーとなる。
-- 一旦、制約を削除 SQL> alter table syain drop constraint fk; 表が変更されました。
on delete set null
SQL> alter table syain add constraint fk foreign key (bcode)
references bumon (code) on delete set null;
表が変更されました。
SQL> delete from bumon where code = '03'; 1行が削除されました。
→ 削除成功(親)
SQL> select * from bumon; CODE BNAME ---- -------------------- 01 1部 02 2部
SQL> select * from syain; ID UNAME BCOD ---------- -------------- ---- 10001 社員1 01 10002 社員2 01 10003 社員3 02 10004 社員4 02
→ 従属する子レコード(ID:10005、10006)が削除された。
-- 一旦、制約を削除 SQL> alter table syain drop constraint fk; 表が変更されました。
on delete cascade
SQL> alter table syain add constraint fk foreign key (bcode)
references bumon (code) on delete cascade;
表が変更されました。
SQL> delete from bumon where code = '03'; 1行が削除されました。
→ 削除成功(親)
SQL> select * from bumon; CODE BNAME ---- -------------------- 01 1部 02 2部
SQL> select * from syain; ID UNAME BCOD ---------- -------------- ---- 10001 社員1 01 10002 社員2 01 10003 社員3 02 10004 社員4 02
→ 従属する子レコード(ID:10005、10006)が削除された。
-- 制約を削除 SQL> alter table syain drop constraint fk; 表が変更されました。
まとめ
on 句を指定する場合、対象行を NULL にするのか Update するのか、
削除してしまうのか、要件に応じて使い分ける必要がある。
この例では部が統合されただけなので、on delete cascade は妥当でない。
(社員5、6がクビということになってしまう!)
本来なら、以下のような方法を検討する。
on 句なしの場合
予め、社員マスタの対象行の bcode を ’01’か’02’に Update しておき、
部門マスタから3部を削除する。(従属対象行が0件)
on delete set null の場合
部門マスタから3部を削除した後、NULL がセットされた
社員マスタの対象行の bcode を ’01’か’02’に Update する。

