在本教程中,您将学习如何使用oracle外键来建立表与表之间的关系。
外键就是表与表的关系,比如:一个表的一例引用另外一个表的一列。 我们从一个简单例子开始,清楚地理解它的概念。
假设,有两个表:supplier_groups
和supplier
分别用来存储供应商分组和供应商信息,如下创建语句:
create table supplier_groups(
group_id number generated by default as identity,
group_name varchar2(255) not null,
primary key (group_id)
);
create table suppliers (
supplier_id number generated by default as identity,
supplier_name varchar2(255) not null,
group_id number not null,
primary key(supplier_id)
);
supplier_groups
表存储供应商组,例如一次性供应商,第三方供应商和跨公司供应商。 每个供应商组可能有零个,一个或多个供应商。
suppliers
表存储供应商信息。每个供应商必须属于一个供应商组织。
supplier_groups
和supplier
表之间的关系是一对多关系。换句话说,一个供应商组有许多供应商,而每个供应商必须属于一个供应商组。
suppliers
表中的group_id
用于建立suppliers
和supplier_groups
表中的行之间的关系。
在suppliers
表中插入一行之前,必须在supplier_groups
表中查找现有的group_id
,并使用该值进行插入。
假设supplier_groups
表包含以下数据:
insert into supplier_groups(group_name)
values('one-time supplier');
insert into supplier_groups(group_name)
values('third-party supplier');
insert into supplier_groups(group_name)
values('inter-co supplier');
select
*
from
supplier_groups;
执行上面查询语句,得到以下结果 -
要插入新的第三方供应商,必须指定group_id
的值为:2
,如下所示:
insert into suppliers(supplier_name, group_id)
values('toshiba', 2);
它按预期那样工作。不过,下面的说法也适用:
insert into suppliers(supplier_name, group_id)
values('wd',4);
supplier_groups
表没有分组id
为4
的行,但没有阻止您将其插入到suppliers
表中,这是一个问题。
例如,以下查询无法获得所有供应商及其分组:
select
supplier_name,
group_name
from
suppliers
inner join supplier_groups
using(group_id);
执行上面查询代码,得到以下结果 -
如您所见,wd
供应商在结果集中缺失。
解决此问题的一个解决方案是使用oracle外键约束来强制supplier_groups
和suppliers
表中的行之间建立外键关系。
首先,删除suppliers
表:
drop table suppliers;
其次,用外键约束重新创建suppliers
表:
create table suppliers (
supplier_id number generated by default as identity,
supplier_name varchar2(255) not null,
group_id number not null,
primary key(supplier_id),
foreign key(group_id) references supplier_groups(group_id)
);
在这个语句中,新增了以下子句:
foreign key(group_id) references supplier_groups(group_id)
该子句指示suppliers
表中的group_id
列定义为引用了supplier_groups
表的group_id
列做为外键。
这样,这个约束就被oracle强制执行了。 换句话说,试图在suppliers
表中插入一行不与supplier_groups
表中的任何行相对应的行时将失败,如果试图从supplier_groups
表中删除suppliers
表中存在相关行时,也会出现错误。
suppliers
表称为子表,而supplier_groups
称为父表。 为了扩展父子分类层次关系,从父表(supplier_groups
)获取主键值并将其插入到子表(suppliers
)中,即子表使用foreign key
时,它继承父表的外键列(group_id
)。
顺便说一下,参照完整性的概念就是保持和执行这种父子关系。
以下语句有效,因为supplier_groups
表有group_id
列的值是:1
的一行:
insert into suppliers(supplier_name, group_id)
values('toshiba',1);
但是,执行以下语句将失败:
insert into suppliers(supplier_name, group_id)
values('wd',4);
因为supplier_groups
没有id
为4
的行。所以会发出以下是错误消息:
sql error: ora-02291: integrity constraint (ot.sys_c0010646) violated - parent key not found
同样,试图删除supplier_groups
表中group_id
列值为1
的行将失败:
delete
from
supplier_groups
where
group_id = 1;
oracle发布了以下错误消息:
sql error: ora-02292: integrity constraint (ot.sys_c0010654) violated - child record found
由于suppliers
表(子表)有一个引用行被删除的行。
oracle允许创建,添加,删除,禁用和启用外键约束。
以下语句说明创建表时创建外键约束的语法:
create table child_table (
...
constraint fk_name
foreign key(col1, col2,...) references parent_table(col1,col2)
on delete [ cascade | set null ]
);
下面来仔细看看一下这个语句。
首先,要显式地为外键约束指定一个名称,可以使用constraint
子句,后跟名称。 constraint
子句是可选的。如果忽略它,oracle会为外键约束分配一个系统生成的名字。
其次,指定foreign key
子句,将一个或多个列定义为具有外键列引用的列的外键和父表。
第三,当删除父表中的行时,使用on delete
子句来指定结果。
null
。与主键约束不同,表可能有多个外键约束。
将外键约束添加到表中
如果要将外键约束添加到现有表中,请按如下所示使用alter table
语句:
alter table child_table
add constraint fk_name
foreign key (col1,col2) references child_table (col1,col2);
删除外键约束
要删除外键约束,请使用下面的alter table
语句:
alter table child_table
drop constraint fk_name;
禁用外键约束
要暂时禁用外部约束,请使用以下alter table
语句:
alter table child_table
disable constraint fk_name;
启用外部约束
同样,也可以使用alter table
语句启用禁用的外键约束:
alter table child_table
enable constraint fk_name;
在本教程中,您已学习如何使用oracle外键约束来强制表之间的关系。