前段时间有问到这个问题,有位仁兄告诉我说使用延迟约束可以实现,但一直没有实践一下,今天突然想起,便做了一下试验,果然如此!呵呵,现将过程共享一下
问题:在oracle里建外键的时候可以指定随主表的主键记录删除而删除或改为NULL或不做任何操作这样三种选择,因此我们可以很容易实现比sqlserver更为灵活的级联删除功能,但在sqlserver里还有一种功能叫级联更新,即我修改了主表的主键值,从表相关的外键值也随之更新,而oracle里没有!虽然建立主外键关系之后,主表的主键值不应该经常修改,可有时候需求就是这么怪怎么办?
解决方式:
1.在建外键时使用延迟约束,即完整性会等到提交时再检查
2.在主表建立触发器,after update时判断主键是否被修改,如果发现主键被修改,则主动将从表的外键值进行相应的修改
目的:在程序里修改主表主键值时变得很简单了,只要直接修改提交即可,无需理会从表中的外键值是否正确匹配了。
试验过程:
sys@182.183> conn scott/tiger
Connected.
scott@182.183> create table t1(a varchar2(5) primary key);
Table created.
scott@182.183> create table t2(k number primary key,a varchar2(5),constraint fk_t2 foreign key(a) references t1(a) on delete cascade initially deferred);
Table created.
scott@182.183> create or replace trigger t1_update_cascade
2 after update on t1
3 for each row
4 begin
5 if :old.a<>:new.a then
6 update t2 set a=:new.a where a=:old.a;
7 end if;
8 end;
9 /
Trigger created.
scott@182.183> insert into t1 values('11111');
1 row created.
scott@182.183> insert into t1 values('22222');
1 row created.
scott@182.183> insert into t2 values(1,'11111');
1 row created.
scott@182.183> insert into t2 values(2,'11111');
1 row created.
scott@182.183> insert into t2 values(3,'22222');
1 row created.
scott@182.183> commit;
Commit complete.
scott@182.183> select * from t1;
A
-----
11111
22222
scott@182.183> select * from t2;
K A
---------- -----
1 11111
2 11111
3 22222
scott@182.183> update t1 set a='33333' where a='22222';--级联更新
1 row updated.
scott@182.183> commit;
Commit complete.
scott@182.183> select * from t1;
A
-----
11111
33333
scott@182.183> select * from t2;
K A
---------- -----
1 11111
2 11111
3 33333
scott@182.183> delete t1 where a='11111';--级联删除,这个本来就很容易实现的
1 row deleted.
scott@182.183> commit;
Commit complete.
scott@182.183> select * from t1;
A
-----
33333
scott@182.183> select * from t2;
K A
---------- -----
3 33333
转载于:https://www.cnblogs.com/yangdihuan/archive/2011/04/14/2016017.html