参照完整性
表的一列或几列的组合的值在表中唯一地指定一行记录,选择这样的一列或多列的组合作为主键可实现表的实体完整性,通过定义PRIMARY KEY约束来创建主键。
外键约束定义了表与表之间的关系,通过将一个表中一列或多列添加到另一个表中,创建两个表之间的连接,这个列就成为第二个表的外键,通过定义FOREIGN KEY约束来创建外键。
使用PRIMARY KEY约束或UNIQUE约束来定义主表主键或唯一键,FOREIGN KEY约束来定义从表外键,可实现主表与从表之间的参照完整性。
定义表间参照关系的步骤是先定义主表主键(或唯一键),再定义从表外键。
使用SQL Developer 实现参照完整性
【例】使用SQL Developer,在stsys数据库中建立student表和score表的参照关系,再删除表间参照关系。
(1)按照前面介绍的方法定义主表主键,此处已定义student表的sno列为主键。
(2)启动”SQL Developer”,在”连接”节点下打开数据库连接”sys_stsys”,展开“表”节点,选中表score,单击鼠标右键,在弹出的快捷菜单中选择”编辑”命令,出现“编辑表”窗口,单击“外键”选项。
(3)单击“添加”按钮,在右边的“名称”栏中输入外键的名称,这里是score_student_FK1,在“引用表”栏中输入引用表的名称,这里是student,在“关联”栏的“本地列”中显示可用于创建外键的列,可以在下拉列表框中选择,这里选择sno,则在”student上的引用列”显示sno,如图所示。
4)单击 “确定”按钮,完成表间参照关系的创建。
(5)在上图所示的界面中,选择需要删除的外键,这里是score_student_FK1,单击“删除”按钮,单击“确定”按钮,即可删除选择的外键。
使用PL/SQL语句创建表间参照关系
创建主键(PRMARY KEY约束)及唯一键(UNIQUE约束)的方法在前面已作介绍,这里介绍通过PL/SQL语句创建外键的方法。
1)创建表的同时定义外键
语法格式:
CREATE TABLE <从表名>
( <列定义> [ CONSTRAINT <约束名> ] REFERENCES <主表名>[ ( <列名> [ ,...n ] ) ]
[,…n]
[ [ CONSTRAINT <约束名> ] [ FOREIGN KEY ( <列名> [,...n ] ) [<参照表达式>]]
)
其中
<参照表达式>::=
REFERENCES <主表名>[ ( <列名> [ ,...n ] ) ]
[ ON DELETE { CASCADE | SET NULL } ]
说明:
可以定义列的外键约束和表的外键约束。
定义列的外键约束在列定义的后面使用REFERENCES关键字定义外键,其对应的主表名的主键或唯一键的列名,在主表名后面的括号中指定。
定义表的外键约束在列定义的后面使用FOREIGN KEY关键字定义外键,并在后面包含要定义的列。
定义外键定义有以下参照动作:
ON DELETE CASCADE:定义级联删除,从主表删除数据时自动删除从表中匹配的行。
ON DELETE SET NULL:从主表删除数据时设置从表中对应外键键列为NULL。 如果未指定动作,当删除主表数据时,如果违反外键约束,操作会被禁止。
【例1】创建stu表,字段名与student表相同,其中sno列作为外键,与已建立的以sno列作为主键student表创建表间参照关系,并插入2条记录:121001,刘鹏翔,1992-08-25和121002,李佳慧,1993-02-18。
CREATE TABLE stu
(
sno char(6) NOT NULL REFERENCES student(sno), /*用这种方式定义了sno是外键*/
sname char(8) NOT NULL,
sbirthday date NULL
);
INSERT INTO stu VALUES('121001','刘鹏',TO_DATE('19920825','YYYYMMDD'));
INSERT INTO stu VALUES('121002','李佳',TO_DATE('19930218','YYYYMMDD'));
【例2】在stu表中,插入1条student表中不存在学号的记录:121005,王晓燕,1993-10-28;在student表中,删除1条stu表中已存在学号的记录:121001,刘鹏翔,1992-08-25。
INSERT INTO stu VALUES('121005','王晓燕',TO_DATE('19931028','YYYYMMDD'));
在stu表中插入的1条记录,其学号在student表中不存在,违反FOREIGN KEY约束,系统报错,拒绝插入。
DELETE FROM student
WHERE sno='121001';
在student表中删除1条记录,其学号在stu表中已存在,违反FOREIGN KEY约束,系统报错,拒绝删除。(要先删了从表的才能删主表的)
【例3】创建sco表,字段名与score表相同,以学号、课程号组合作为外键,与已建立的以学号、课程号组合作为主键的score表创建表间参照关系,并且当删除score表中的记录时同时删除sco表中与主键对应的记录。
创建sco表,定义了外键和级联删除,其语句如下。
CREATE TABLE sco
(
sno char(6)NOT NULL,
cno char(4)NOT NULL,
grade int NULL,
CONSTRAINT FK_sco FOREIGN KEY(sno,cno) REFERENCES score (sno,cno) /*前一个(sno,cno)引用了score的(sno,cno),score是主表*/
ON DELETE CASCADE
);
在从表sco表插入与主表score同样的18条记录。
由于在建立score表和sco表的表间参照关系时定义了级联删除,当删除score表cno为1004的记录时自动删除stu表中匹配行。
DELETE FROM score
WHERE cno='1004';
对主表执行结果进行查询,可以看出,主表已删除cno为1004的3条记录,剩下15条记录。
SELECT *
FROM score;
对从表执行结果进行查询,此时从表已自动删除cno为1004的3条记录,剩下15条记录,实现了级联删除。
SELECT *
FROM sco;
2)通过修改表定义外键
语法格式:
ALTER TABLE <表名>
ADD CONSTRAINT <约束名>
FOREIGN KEY( <列名>[,…n])
REFERENCES <主表名>(<列名>[,…n]) <参照表达式>
【例】修改stsys数据库中score表的定义,将它的“课程号”列定义为外键,假设course表的“课程号”列已定义为主键。
ALTER TABLE score
ADD CONSTRAINT FK_score_course FOREIGN KEY(cno)
REFERENCES course(cno); /*score的cno引用了course的cno*/
2.使用PL/SQL语句删除表间参照关系
语法格式:
ALTER TABLE <表名>
DROP CONSTRAINT <约束名>[,…n];
【例】删除以上对score课程号列定义的FK_score_course外键约束。
ALTER TABLE score
DROP CONSTRAINT FK_score_course;
综合训练
(1)在stsys数据库中建立3个表:st,co,sc
CREATE TABLE st /* 学生表 */
( sno char(5), /* 学号 */
sname char(10), /* 姓名 */
age int, /* 年龄 */
sex char(2) /* 性别 */
);
CREATE TABLE co /* 课程表 */
( cno char(5), /* 课程号 */
cname char(10), /* 课程名 */
teacher char(10) /* 任课教师 */
);
CREATE TABLE sc /* 成绩表 */
( sno char(5), /* 学号 */
cno char(5), /* 课程号 */
grade int /* 分数 */
);
(2)将st表中sno修改为主键。
ALTER TABLE st
MODIFY sno NOT NULL;
ALTER TABLE st
ADD (CONSTRAINT PK_sno PRIMARY KEY(sno));
(3)将st表中的age列的值设为应在16~25之间。
ALTER TABLE st
ADD (CONSTRAINT CK_age CHECK(age>=16 AND age<=25));
(4)将sc表中sno设置为引用sc表中sno列的外键。
ALTER TABLE sc
ADD CONSTRAINT FK_sno
FOREIGN KEY (sno) REFERENCES st (sno);
(5)将sc表中cno设置为引用co表中cno列的外键。
ALTER TABLE co
MODIFY cno NOT NULL;
ALTER TABLE co
ADD (CONSTRAINT PK_cno PRIMARY KEY(cno));
ALTER TABLE sc
ADD CONSTRAINT FK_cno
FOREIGN KEY (cno) REFERENCES co (cno);
(6)删除前面所有的限定。
ALTER TABLE sc
DROP CONSTRAINT FK_sno;
ALTER TABLE sc
DROP CONSTRAINT FK_cno;
ALTER TABLE st
DROP CONSTRAINT PK_sno;
ALTER TABLE st
DROP CONSTRAINT CK_age;
ALTER TABLE co
DROP CONSTRAINT PK_cno