(1)什么是数据库的完整性
数据库的完整性:数据库的完整性指的是DBMS应该保证DB的一种特性 在任何情况下的正确性,一致性和有效性
广义的完整性:语义完整性、并发控制、安全控制、DB故障恢复(等等保证完整性的措施);
狭义的完整性:专指的事语义完整性,DBMS通常有专门的完整性管理机制与程序来处理语义完整性问题。
数据库中讨论主要是狭义的完整性:实体完整性、参照完整性、用户自定义完整性、
(2)数据库完整性管理的作用?
防止和避免数据库中不合理数据的出现
注:DBMS应尽可能自动防止DB中语义不合理现象。
(3)DBMS如何实现完整性约束规则
当有DB更新操作时,DBMS完整性控制程序自动按照完整性约束条件进行检查,以确保更新符合语义的完整性。
(4)完整性约束的一般形式:
完整性约束的一般形式:Integrity Constraint ::= ( O,P,A,R)
O:数据集合:约束的对象? 列、多列(元组)、元组集合
P:谓词条件:什么样的约束?
A:触发条件:什么时候检查?
R:响应动作:不满足时怎么办
(5)数据库完整性的分类
按照约束对象分为:
(1)域完整性约束条件 用于一列上的候选值
(2)关系完整性约束条件:施加于关系/table上,对给定table上所要更新的某一候选元组是否可以接受进行约束条件判断,或是对一个关系中的若干元组和另一个关系中的若干元组间的联系是否可以接受进行约束条件判断
按照约束来源分类:
- 来源于模型的约束,例如函数依赖约束、主键约束(实体完整性)、外键约束(参照完整性),只关心数值相等与否,是否允许空值等。
- 来源于用户约束,如用户自定义完整性约束,如限定年龄范围。
按约束状态分类:
- 静态约束:要求DB在任何时候都应该满足条件
- 动态约束:要求DB从一个状态转变为另一个状态应该要满足的条件如工资只能升高 不能降低等等。
(6)SQL语言实现完整性的方式
- 静态约束:列完整性、表完整性
Integrity Constraint:: =(0,P,A,R);
注:A 默认更新时检查 R 默认拒绝更新列约束的实现(一种域约束类型,对单一列的值进行约束)
列约束的实现:
--列约束的实现(一种域约束类型,对单一列的值进行约束)
{ NOT NULL | --//列值非空
[ CONSTRAINT constraintname] --//为约束命名,便于以后撤消
{ UNIQUE-- //列值是唯一
| PRIMARY KEY --//列为主键
| CHECK (search_cond) --//列值满足条件,条件只能使用列当前值
| REFERENCES tablename [(colname) ]
[ON DELETE { CASCADE | SET NULL } ] } }
表约束的实现:
[ CONSTRAINT constraintname ] //为约束命名,便于以后撤消
{ UNIQUE (colname {, colname. . .}) //几列值组合在一起是唯一
| PRIMARY KEY (colname {, colname. . .}) //几列联合为主键
| CHECK (search_condition) //元组多列值共同满足条件
//条件中只能使用同一元组的不同列当前值
| FOREIGN KEY (colname {, colname. . .})
REFERENCES tablename [(colname {, colname. . .})]
[ON DELETE CASCADE] }
注:table_constr表约束:是应用在关系上,即对关系的多列或元组进行约束,列约束是其特例
Create Table Course ( C# char(3) , Cname char(12), Chours integer,
Credit float(1) constraint ctcredit check (Credit >=0.0 and
Credit<=5.0 ), T# char(3) references Teacher(T#) on delete
cascade );
Create Table Course ( C# char(3) , Cname char(12), Chours integer,
Credit float(1) constraint ctcredit check (Credit >=0.0 and
Credit<=5.0 ), T# char(3) references Teacher(T#) on delete
cascade, primary key(C#),
constraint ctcc check(Chours/Credit = 20) );
--注:check中的条件是SELECT-FROM-WHERE内任何WHERE后的子句,包含子查询。
Create Table SC ( S# char(8) check( S# in (select S# from student)) ,
C# char(3) check( C# in (select C# from course)) ,
Score float(1) constraint ctscore check (Score>=0.0 and
Score<=100.0);
撤销约束 或者修改约束
ALTER TABLE tblname
[ADD ( { colname datatype [DEFAULT {default_const|NULL} ]
[col_constr {col_constr...} ] | , table_constr }
{, colname ...}) ]
[DROP { COLUMN columnname | (columnname {, columnname…})}]
[MODIFY ( columnname data-type
[DEFAULT {default_const | NULL } ] [ [ NOT ] NULL ]
{, columnname . . .})]
[ADD CONSTRAINT constr_name]
[DROP CONSTRAINT constr_name]
[DROP PRIMARY KEY ] ;
--示例:若要再对SC表的score进行约束,比如分数在0~150之间,则可新增
--加一个约束。在Oracle中增加新约束,需要通过修改列的定义来完成
Alter Table SC
Modify ( Score float(1) constraint nctscore check (Score>=0.0 and
Score<=150.0) );
用SQL语言实现数据库的完整性:断言
断言:ASSERTION
一个断言就是一个谓词表达式,它表达了希望数据库总能满足的条件,表约束和列约束就是一些特殊的断言。SQL还提供了复杂条件表达式的断言。CREATE ASSERTION<assertion-name> CHECK(predicate) 当一个断言创建后,系统将检测器有效性,并且每一次测试更新是否违背该断言。断言测试增加了数据库维护的负担,要小心使用复杂的断言。
2、动态约束 触发器
触发器:Trigger
CREATE TABLE中的表约束和列约束基本上都静态约束,也是对单一列或者元组的约束,为实现动态约束以及多个元组之间的约束,就需要触发器技术。所谓的触发器技术,就是一种过程完整性约束程序,该程序可以在特定的时刻被自动的触发执行。
CREATE TRIGGER trigger_name BEFORE | AFTER
{ INSERT | DELETE | UPDATE [OF colname {, colname...}] }
ON tablename [REFERENCING corr_name_def {, corr_name_def...} ]
[FOR EACH ROW | FOR EACH STATEMENT]
//对更新操作的每一条结果(前者),或整个更新操作完成(后者)
[WHEN (search_condition)] //检查条件,如满足执行下述程序
{ statement //单行程序直接书写,多行程序要用下行方式 互斥操作,这些操作要么一次执行,要么不执行
| BEGIN ATOMIC statement; { statement;...} END }比如在一次更新操作之前,或者一次更新操作之后。
注:触发器Trigger意义:当某一事件发生时(Before|After),对该事件产生的结果(或是每一元组,或是整个操作的所有元组), 检查条件search_condition,如果满足条件,则执行后面的程序段。条件或程序段中引用的变量可用corr_name_def来限定。
事件:BEFORE | AFTER { INSERT | DELETE | UPDATE …}
当一个事件(Insert, Delete, 或Update)发生之前Before或发生之后After触发操作发生,执行触发器操作需处理两组值:更新前的值和更新后的值,这两个值由corr_name_def的使用来区分
corr_name_def的定义
{ OLD [ROW] [AS] old_row_corr_name //更新前的旧元组命别名为
| NEW [ROW] [AS] new_row_corr_name //更新后的新元组命别名为
| OLD TABLE [AS] old_table_corr_name //更新前的旧Table命别名为
| NEW TABLE [AS] new_table_corr_name //更新后的新Table命别名为
}
注:corr_name_def将在检测条件或后面的动作程序段中被引用处理
--示例:
--设计一个触发器当进行Teacher表更新元组时, 使其工资只能升不能降
create trigger teacher_chgsal before update of salary
on teacher
referencing new x, old y
for each row when (x.salary < y.salary)
begin
raise_application_error(-20003, 'invalid salary on update');
--//此条语句为Oracle的错误处理函数
end;