8.4.2.2 建立完整性约束
约束可以在建表时定义,也可以在修改表时增加约束。使用CREATE TABLE或ALTER TABLE语句可以建立约束。假如没有给约束提供名字,Oracle指派一个系统产生的约束名。假如希望给约束提供一个名字,必须指定CONSTRAINT关键字,在关键字后紧跟约束名字。
假如完整性约束是作用于单列的约束,则可以在列一级定义约束。
假如完整性约束是作用于多列的约束,则必须在表一级定义约束,在括号内列出多个列名,多个列之间用逗号分隔。
1.列一级的约束
在建表时定义列的同时可以定义约束,这种约束作用于单列。定义NOT NULL约束必须定义在列一级,这种约束在定义列的同一行内定义。
定义列一级约束的语法如下:
列名 数据类型[CONSTRAINT 约束名]列一级约束从句[Disable|Enable]
其中,列一级约束从句的语法如下:
{[NOT]NULL
PRIMARY KEY
UNIQUE
REFERENCES 表名[(列名)][ON DELETE{CASCADE|SET NULL}]
CHECK(condition)}
ON DELETE CASCADE表示当删除父表(即被参照表)数据时,将子表(即参照表)中与父表被删除数据相关的数据一起删除。
ON DELETE SET NULL表示当删除父表数据时,将子表中与父表被删除数据相关的数据被设成NULL。
[NOT]NULL用于指定该列是否允许包含NULL值,定义NOT NULL约束。
PRIMARY KEY用于定义主键约束,表示该列是一个主键列。
UNIQUE用于定义唯一性约束,表示该列的值必须唯一。
REFERENCES用于定义与其他表之间的参考完整性约束,即外键约束。该列是一个与其他表连接的公共列。默认情况是该从句后面没有指定ON DELETE子句,表示如果要删除父表的某个元组,而子表中存在若干元组,其外键值与父表中删除元组的主键值相同,系统拒绝此删除操作。
CHECK用于定义CHECK约束,condition定义了该列必须满足的条件。
DISABLE表示约束失效。假如约束失效,Oracle服务器不检查该约束。
ENABLE表示约束生效。只有约束生效,Oracle服务器才在DML语句结束时检查约束。ENABLE是默认值。
例8-58 建立student表时规定列一级约束,约束名由Oracle自动命名。
SQL>CREATE TABLE student(sno char(8)PRIMARY KEY,
sname char(20)NOT NULL,
*** char(1),
age int,
dept char(15))
例8-59 建立employee表,指定列一级主键约束和not null约束。用户自己命名约束名。
SQL>CREATE TABLE employee(
empno number(4)CONSTRAINT emppk PRIMARY KEY,
ename varchar2(20)CONSTRAINT empnn NOT NULL,
deptno number(4))
2.表一级的约束
假如在建表或修改表时定义除了NOT NULL约束以外的其他约束时,如果约束是作用于多列的约束,则必须在表一级定义而不能在列一级定义约束。
定义表一级约束的语法如下:
[CONSTRAINT 约束名]表一级约束从句[Disable|Enable]
其中,表一级约束从句的语法如下:
{[PRIMARY KEY(列名1[,列名2]……)
UNIQUE(列名1[,列名2]……)
FOREIGN KEY(列名1[,列名2]……)
REFERENCES 表名[(列名1[,列名2]……)]
[ON DELETE{CASCADE|SET NULL}]
CHECK(condition)}
各关键字的含义与定义单列约束时的各关键字含义一致。
注意:建议采用一个标准的命名规则为约束取名,不采用系统默认的约束名字。
例8-60 在sc表中定义表一级的约束条件。规定主键是(sno,cno),并且sno参照student 表的sno,cno参照course表的cno,成绩grade的值要么是空值,表示还没有成绩,要么在0到100之间。可用CHECK约束加以限制。
SQL>CREATE TABLE sc(sno char(5),
cno char(8),
grade int,
PRIMARY KEY(sno,cno),
FOREIGN KEY(sno)references student(sno),
FOREIGN KEY(cno)references course(cno),
CHECK((grade is null)or(grade between 0 and 100)))
例8-61 使用ALTER TABLE语句修改employee表,增加外键约束。
SQL>ALTER TABLE employee
ADD(CONSTRAINT empfk FOREIGN KEY(deptno)
REFERENCES dept(deptno));
8.4.2.3 各种完整性约束的特点
1.NOT NULL约束
NOT NULL约束有下列特性。
(1)只能定义在列一级。
(2)当使用CREATE TABLE命令建表时可以定义NOT NULL约束。
例8-62 在建立orders表的同时,在ordernum列上定义一个用户命名的约束,在orderdate列上定义一个系统命名的约束。
SQL>CREATE TABLE orders(
ordernum number(4)CONSTRAINT ordernn NOT NULL,
orderdate date NOT NULL)
(3)可以使用ALTER TABLE MODIFY命令给一张已经存在的表中的列增加或删除NOT NULL约束。
例8-63 删除orders表上的orderdate列上的NOT NULL约束。
SQL>ALTER TABLE orders MODIFY orderdate NULL;
2.UNIQUE约束
UNIQUE(唯一性)约束有下列特性。
(1)如果定义单列唯一键,该约束可以在列一级定义。如果定义多列的唯一键,该约束必须在表一级定义,多列的唯一键最多只能指定32个列。
(2)假如约束是失效的(DISABLE),则不需要索引。
(3)假如约束是生效的(ENABLE),Oracle在唯一键列上隐式地建立一个唯一性索引,约束将使用该索引保证唯一。假如在表的相同列上已经存在一个唯一性索引,Oracle使用已经存在的索引。
(4)UNIQUE约束允许在约束列上出现NULL值。
例8-64 在emp表一级上定义一个唯一性约束,该约束有两个约束列。
SQL>ALTER TABLE emp ADD CONSTRAINT empuq UNIQUE(empno,deptno);
例8-65 在emp表上增加一个新列ssn,在该列上定义一个列一级的唯一性约束。
SQL>ALTER TABLE emp ADD ssn varchar2(20)CONSTRAINT ssnuq UNIQUE
3.PRIMARY KEY约束
PRIMARY KEY约束有下列特性。
(1)除了在PRIMARY KEY主键列上不允许有NULL值以外,UNIQUE约束的所有特性都适合PRIMARY KEY约束。
(2)一张表上只能有一个主键。
(3)如果Primary key约束是生效的,Oracle隐式地为主键中的每一列定义唯一性索引和NOT NULL约束。隐式建立的索引可以与其他的索引一样管理,但不能被显式地删除。
例8-66 在建表时定义了一个主键约束和唯一约束。
SQL>CREATE TABLE employee
(deptno number(4),
empno number(4),
ename varchar2(20)NOT NULL,
ssn varchar2(20),
sal number(9,2)CHECK(sal>1000),
CONSTRAINT eemployeepk PRIMARY KEY(deptno,empno),
CONSTRAINT ssnuq UNIQUE(ssn));
4.FOREIGN KEY 约束
FOREIGN KEY是参照表(称为子表)中的一列或多列,被参照键(referenced key)是被参照表(称为父表)中的主键列或唯一键列(或多列)。
外键约束有下列规则。
(1)定义外键约束时必须先定义父表,并且要求定义父表的主键,作为被参考键。
(2)一个外键约束可以在列一级定义,也可以在表一级定义,假如外键有多列,应该在表一级定义。
(3)外键列和被参考键列可以在同一张表中,即自参考完整性约束。
(4)在外键列上可以有NULL值。
(5)ON DELETE从句指定当父表中的一行被删除时,子表中与父表被删除的行相关的行如何处理。分以下三种情况。
指定ON DELETE CASCADE:表示删除父表中的主记录时,子表中相关的子记录一起被删除。
例如,删除student表sno98002的元组时,将sc表中所有sno98002的4个元组一起删除。
指定ON DELETE SET NULL:表示删除父表中的主记录时,子表中相关的子记录被设成NULL。
例如,删除student表sno98002的元组时,将sc表中所有sno98002的4个元组的SNO值置为NULL。
省略ON DELETE从句:表示如果子表中存在与被删的主记录相关的子记录,不允许删除父表中的主记录,必须首先删除子记录,提交,然后才能删除父记录。
例如,删除student表sno98002的元组时,如果在sc表中有sno98002的元组,则拒绝删除student表sno98002的元组。
例8-67 修改city表增加city表与state表之间的参考约束,如果删除state表中的行时,将city表中相关的行设成NULL。
SQL>ALTER TABLE city ADD CONSTRAINT statefk
FOREIGN KEY(countrycode,statecode)
REFERENCES STATE(countrycode,statecode)
ON DELETE SET NULL
(6)在删除和截断父表之前,必须先删除外键约束。可用下列命令完成删除表和删除外键约束两项任务。
SQL>DROP TABLE 表名CASCADE CONSTRAINTS;
(7)当往子表中插入或更新数据时,插入的外键值或更新的外键值必须在父表的被参考键上已经存在时才允许插入或更新。
例如,在student表中没有sno95001的学生记录时,往sc表中插入sno95001的选课记录时被拒绝。
(8)只有当子表中没有一个外键值与要修改的父表中主键值相同时,系统才能修改父表的主键,否则拒绝此修改操作。
例如,将student表sno98002的元组中的sno修改为98003时,如果在sc表中有SNO98002的元组,则拒绝修改student表sno98002的元组。
5.CHECK约束
CHECK约束有下列特性。
(1)该约束可以在列一级或表一级上定义。
(2)在CHECK从句中指定的条件应该得到一个布尔型的结果,该条件可以参考同一行中其他列的值,不能使用查询语句。
(3)在CHECK约束的条件中不能使用系统函数(如:SYSDATE、USER、USERENV、UID等)和伪列(如:ROWNUM、CURRVAL、NEXTVAL、LEVEL等)。
(4)在一列上可以定义多个CHECK约束,该列可以有一个NULL值。
(5)可以使用CREATE TABLE或ALTER TABLE命令建立CHECK约束。
例8-68 建立emp表时在sal列定义了CHECK约束,规定sal大于1000、bonus大于0。如果往emp表中插入记录时sal小于1000或者bonus小于0,则Oracle不允许插入。
SQL>CREATE TABLE emp(
empno number(4)NOT NULL,
ename varchar2(20),
sal number(9,2)CONSTRAINT empck CHECK(sal>1000),
bonus number(9,2)CONSTRAINT empk1 CHECK(bonus>0))
例8-69 修改emp表,增加一个CHECK约束,保证bonus必须小于SAL。这样bonus列上有两个CHECK约束。
SQL>ALTER TABLE emp
ADD CONSTRAINT empck2 CHECK(bonus<sal)
8.4.2.4 修改完整性约束的状态
Oracle系统中一个完整性约束有下列两种状态:ENABLE和DISABLE。
约束生效(ENABLE)是联机事务处理中一个约束的默认状态。假如约束处于该状态,表中已经存在的数据必须满足约束条件,另外,将来输入的数据也必须满足约束条件。
约束失效(DISABLE)对已经存在的数据或将来输入的数据或所做的修改都不检查是否满足约束条件。
1.使完整性约束失效
当将一个约束失效时,就相当于没有约束。可以采用下列三种方法将约束失效。
(1)建立失效的约束
当建立一个约束时,该约束总是自动生效的。可以在定义约束的后面指定DISABLE关键字建立一个失效的约束。
例8-70 修改city和bonus表增加一个失效的约束。
SQL>ALTER TABLE city ADD CONSTRAINT statepk
FOREIGN KEY(countrycode,statecode)
REFERENCES STATE(countrycode,statecode)DISABLE
SQL>ALTER TABLE bonus
ADD CONSTRAINT bonusck CHECK(bonus>0)DISABLE
当然,在建立自动生效的约束后,可以使用命令使得约束失效或再将失效的约束生效。
(2)使用ALTER TABLE语句的DISABLE从句将一个约束失效
在装入大量数据之前,应该将约束失效。可以使用ALTER TABLE语句的DISABLE从句将一个约束失效。使得约束失效的语法如下:
ALTER TABLE 表名
DISABLE{CONSTRAINT 约束名
PRIMARY KEY
UNIQUE(列名1[,列名2]……)}
[CASCADE]
其中:CASCADE表示将主外键约束关系一起失效,先将外键约束失效,再将主键约束失效。
注意:
除了主键约束或唯一性约束以外,所有其他约束必须指定约束名。当指定UNIQUE和列名时将唯一性约束失效,指定PRIMARY KEY时将主键约束失效。
当将主键约束或唯一性约束失效时,Oracle删除相关的唯一性索引。当将这些约束重新生效时,Oracle建立相关的唯一性索引。
假如一个主键约束或唯一性约束被一个生效的外键约束参考时,不能将主键约束或唯一性约束失效。使用CASCADE关键字可以将所有外键约束失效,然后将主键约束或唯一性约束失效。
例8-71 将emp表上的empuq约束失效。
SQL>ALTER TABLE emp DISABLE CONSTRAINT empuq;
例8-72 将dept表上的主键约束失效,同时将所有外键约束一起失效。
SQL>ALTER TABLE dept DISABLE PRIMARY KEY CASCADE;
3.使用ALTER TABLE命令的MODIFY CONSTRAINT从句使得约束失效
也可以使用ALTER TABLE命令的MODIFY CONSTRAINT从句使得约束失效。语法如下:
ALTER TABLE 表名
MODIFY CONSTRAINT 约束名
DISABLE
[CASCADE]
其中各关键字的含义与上述ALTER TABLE DISABLE CONSTRAINT的语法中的关键字一致,在此不再解释。
例8-73 将emp表上的empuq约束失效。
SQL>ALTER TABLE emp MODIFY CONSTRAINT empuq DISABLE
或
SQL>ALTER TABLE emp DISABLE CONSTRAINT empuq;
例如:使用CASCADE可以将主外键约束一起失效。
SQL>ALTER TABLE dept MODIFY CONSTRAINT deptpk DISABLE CASCADE
2.使得完整性约束生效
可以使用ALTER TABLE语句的ENABLE从句将一个失效的约束生效。当将一个失效的唯一性约束或主键约束生效时,Oracle在唯一键或主键列上建立一个索引。
(1)使用ALTER TABLE命令的ENABLE CONSTRAINT从句将一个约束生效
可以使用ALTER TABLE语句的ENABLE从句将一个当前失效的约束生效。将一个约束生效时需要检验已经存在的数据是否违反约束条件,这是约束生效时的默认值。将一个约束生效的语法如下:
ALTER TABLE 表名
ENABLE{CONSTRAINT 约束名
PRIMARY KEY
UNIQUE(列名1[,列名2]……)}
其中,各关键字的含义与上述将约束失效语法中的关键字一致,在此不再解释。
例8-74 将emp表上的外键约束生效,并且对表中已经存在的数据也要检验。
SQL>ALTER TABLE emp ENABLE CONSTRAINT empfk
(2)使用ALTER TABLE命令的MODIFY CONSTRAINT从句使得约束生效
也可以使用ALTER TABLE命令的MODIFY CONSTRAINT从句使得约束生效。语法如下:
ALTER TABLE 表名
MODIFY CONSTRAINT 约束名
ENABLE
[CASCADE]
其中,各关键字的含义与上述ALTER TABLE命令的MODIFY CONSTRAINT从句使得约束失效的语法中的关键字一致,在此不再解释。
例8-75 将emp表上的empuq约束生效。
SQL>ALTER TABLE emp MODIFY CONSTRAINT empuq ENABLE
例8-76 将主键约束emppk生效。
SQL>ALTER TABLE emp MODIFY CONSTRAINT emppk ENABLE
8.4.2.5 删除完整性约束
当约束不再需要时可以被删除,或者当约束需要被修改但不能直接修改时需要被删除,然后再加约束。删除一个约束的语法如下:
ALTER TABLE 表名
DROP{CONSTRAINT 约束名
PRIMARY KEY
UNIQUE(列名1[,列名2]……)}
[CASCADE]
注意:
使用CASCADE选项可以删除任何外键约束,然后删除唯一性约束和主键约束。
当删除一个主键约束或唯一性约束时,相关的唯一性索引也被删除。
例8-77 删除emp表上的empck约束。
SQL>ALTER TABLE emp DROP CONSTRAINT empck
例8-78 删除emp表empno列上的唯一性约束,必须指定唯一键列名和CASCADE关键字。
SQL>ALTER TABLE emp DROP UNIQUE(empno)CASCADE
例8-79 使用CASCADE删除emp表上的外键约束,然后删除主键约束。
SQL>ALTER TABLE emp DROP PRIMARY KEY CASCADE;
被外键参考的表(父表)只有在删除外键后才能删除,当删除该表时,任何外键约束一起被删除。
8.4.2.6 查询完整性约束信息
约束的名字、约束所在的列名、约束的类型、状态等信息都可以从数据字典视图中获得。
小结
本章主要介绍了数据库管理中涉及的安全性、恢复、并发控制和完整性的基本概念和实现的基本方法,同时介绍Oracle系统是如何实现这四项保护措施的。在并发控制中介绍了并行操作会产生的几个问题,举例说明如何利用封锁机制解决并行操作的问题。在数据库的恢复中介绍故障的种类,以及恢复的实现方法和策略。在安全性和完整性中介绍保证数据安全和正确的基本原理和实现方法,并对实现方法给出了SQL语言中的应用实例。这些实例帮助读者进一步理解基本概念和实现方法。
因为不同的DBMS在安全性、完整性、并发控制和恢复技术几个方面在实现的语法细节上有差别,所以在介绍每一个保护措施的原理和实现方法的同时,详细地介绍在Oracle系统中实现这些保护措施的命令和步骤,并举例说明。可以在Oracle系统上按步骤进行具体操作,加深对这些原理和方法的理解,以及能够很快掌握和运用Oracle系统提供的数据库保护的功能。学生应把重点放在掌握基本概念和基本方法上。
习题
1.试述事务的概念及事务的4个特性。
2.数据库中为什么要有恢复子系统?恢复子系统的功能是什么?
3.数据库运行过程中可能产生的故障有哪几类?哪些故障影响事务的正常执行,但不破坏数据库中的数据?哪些故障破坏数据库中的数据?
4.事务的COMMIT操作和ROLLBACK操作的功能是什么?
5.UNDO操作和REDO操作的功能是什么?
6.数据库恢复的技术有哪些?
7.数据库转储的意义是什么?试比较各种数据转储方法。
8.登记日志文件时为什么必须先写日志文件,后写数据库?
9.如何进行事务故障的恢复?如何进行系统故障的恢复?如何进行介质故障的恢复?
10.Oracle系统备份与恢复的种类有哪些?物理备份与恢复方法又可分几类?
11.并发操作可能会产生哪几类数据不一致问题?如何解决?
12.什么是封锁?封锁的类型有哪几种?
13.有几级封锁协议?不同的封锁协议的主要区别是什么?分别能解决哪些数据不一致问题?
14.什么是活锁?什么是死锁?如何预防和检测死锁?
15.试述“串行调度”和“可串行化调度”的区别。
16.Oracle系统中的锁模式有哪些?这些锁允许哪些操作?阻止哪些操作?
17.试述实现数据库安全性控制的常用方法和技术。
18.什么是“权限”?解释权限的转授和回收。
19.视图机制有哪些优点?
20.现有两个关系模式:
职工(职工号,姓名,年龄,职务,工资,部门号)
部门(部门号,名称,经理号,地址,电话号码)
请用SQL的GRANT和REVOKE语句完成下列权限的授予和回收功能。
(1)用户王明对两个表拥有SELECT 权限。
(2)用户李勇对两个表拥有INSERT和DELETE权限。
(3)用户刘星对职工表有SELECT权限,对工资字段有UPDATE权限。
(4)用户张星具有修改这两个表结构的权限。
(5)用户张平具有这两个表的所有权限,并具有转授给其他用户的权限。
(6)用户杨兰具有从每个部门职工中SELECT最高工资、最低工资、平均工资的权限,他不能查看每个人的工资。
21.Oracle系统中的权限分哪几类?数据库审计分哪几类?
22.什么是数据库的完整性?DBMS完整性子系统的功能是什么?
23.数据库完整性与安全性概念的区别和联系是什么?
24.数据库的完整性约束条件分几类?
25.参照完整性约束条件中,删除主表(被依赖表)的记录时,对从表(依赖表)中的记录采取哪三种方法?
26.设教学数据库中有下列三个关系模式:
s(s#,sname,age,***)
sc(s#,c#,grade)
c(c#,cname,teacher)
试用多种方法定义下列完整性约束。
(1)在关系s中插入的学生年龄应在16~25岁之间。
(2)在关系sc中插入记录时,其s#值和c#值必须分别在s和c表中出现。
(3)在关系sc中的grade值必须在0~100之间或为空。
(4)在删除关系c中的一条记录时,首先要把关系sc中具有同样c#值的记录全部删除。