外键, on delete cascade和on delete set null

外键


create table t1
(c1 number(10) primary key);

create table t2
(c1 number(10) references t1(c1),
c2 varchar2(10));

T2 表的 C1 字段与 T1 表的 C1 字段建立了外键关系。

T1 叫父表(parent table). T2 叫子表(child table).

先在 T1 表里插入一条数据:


insert into t1 values(123);
commit;

然后在 T2 里尝试插入一条数据:


insert into t2 values(456);

由于 T2 表与 T1 表有外键关系,且 T1 表里没有 456 这条数据,所以报错了:ORA-02291


insert into t2 values(123);
commit;

这样就好了。

尝试删除 T1 里的数据:


delete from t1;

由于T1表只有一条数据,所以没有指定where子句。

子表 T2 引用了父表 T1 里的内容,不能直接删除父表里的数据。

需要先删除子表 T2 里对应的数据:


delete from t2;
delete from t1;
commit;
select * from t1;
select * from t2;

扩展:on delete cascade参数

创建两张表:

T3是父表,T4是子表,子表的外键上指定了on delete cascade参数


create table t3
(c1 number(10),
constraint t3_pk primary key(c1));

create table t4
(c1 number(10),
c2 varchar2(10),
constraint t4_fk foreign key(c1) references t3(c1) on delete cascade);

各插入两条数据:


insert into t3 values(123);
insert into t3 values(456);
insert into t4 values(123,'ABC');
insert into t4 values(456,'DEF');
commit;

这里我们直接删除父表 T3 里的数据:


delete from t3 where c1=123;
commit;

可以看到能直接删除父表里的数据,但是子表里对应的一行数据也被删掉了。 这就是 on delete cascade 参数的作用

扩展:on delete set null 参数

创建两张表:

T5是父表,T6是子表,子表的外键上指定了on delete set null参数


create table t5
(c1 number(10),
constraint t5_pk primary key(c1));

create table t6
(c1 number(10),
c2 varchar2(10),
constraint t6_fk foreign key(c1) references t5(c1) on delete set null);

各插入两条数据:


insert into t5 values(123);
insert into t5 values(456);
insert into t6 values(123,'ABC');
insert into t6 values(456,'DEF');
commit;

我们直接删除父表 T5 里的数据:


delete from t5 where c1=123;
commit;

可以看到能直接删除父表里的数据,但是子表里对应字段的数据变成空值(NULL)了。 这就是 on delete set null 参数的作用

如果父表没有定义主键会怎样?

比如:


create table t7 (c1 number(10));

create table t8
(c1 number(10),
c2 varchar2(10),
constraint t8_fk foreign key(c1) references t7(c1));

提示没有找到唯一或主键约束 ,加个唯一约束看看:


alter table t7 add constraint t7_uk unique(c1);

-- 再执行建表语句
create table t8
(c1 number(10),
c2 varchar2(10),
constraint t8_fk foreign key(c1) references t7(c1));

成功了。

进阶

我们在字段上定义主键约束或唯一约束时,oracle会在该字段创建一个唯一索引

如何查看?



select ui.table_name,ucc.column_name,ui.index_name,
       uc.constraint_name,ui.uniqueness 
from user_indexes ui 
join user_constraints uc on(ui.index_name=uc.index_name) 
join user_cons_columns ucc on(ucc.constraint_name=uc.constraint_name); 

1. 可以看到索引名和约束名是一致的。

2. 创建 T1 表时指定了主键约束,但是没有给约束起名,SYS_C0025178 是系统给的约束/索引名。

3. T1, T3, T5 创建时加了主键约束,而 T7 是创建后加了唯一约束。

那么唯一索引能不能替代唯一约束或主键约束呢???


create table t9 (c1 number(10));

create unique index t9_uidx on t9(c1);

create table t10
(c1 number(10),
c2 varchar2(10),
constraint t10_fk foreign key(c1) references t9(c1));

看来不行。


select distinct ui.table_name,ucc.column_name,uic.column_name,
       ui.index_name,uc.constraint_name,ui.uniqueness 
from user_indexes ui 
left join user_constraints uc on(ui.index_name=uc.index_name) 
left join user_cons_columns ucc on(ucc.constraint_name=uc.constraint_name)
left join user_ind_columns uic on(ucc.column_name=uic.column_name) 
order by ui.table_name;

不过在一些场景下唯一索引确实可以替代主键约束或唯一约束。

比如,GoldenGate 同步时如果找不到表上的主键就会去找该表上的唯一索引 。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值