前言
"<数据库原理及应用>(MySQL版)".以下称为"本书"中4.2.1节和4.2.2节内容
引入
数据库完整性是指数据的正确性和相容性.利用完整性约束,DBMS可帮助用户阻止非法数据的输入
4.2.1 三类完整性规则
这一小节内容就这样读,也挺抽象.代入两个例子就容易理解了.
1.实体完整性规则
分析的结果就是规则4.1:主键的各个属性都不能为空值.
2.参照完整性规则
本书P105中间:参照完整性规则就是定义外键与主键之间的引用规则.
有几个概念:主键,外键,参照关系和被参照关系.其中主键和外键的概念前面已叙述.参照关系是指:当关系A拥有主键a和外键b.关系B用关系A的外键b作为主键时,称为关系A是参照关系,关系B是被参照关系.如图
关系A | 关系B | |||||
属性1(主键a) | 属性2 | 属性3(外键b) | 属性1(外键b) | 属性2 |
简单理解:参照关系作为两个关系中的主要关系,先满足关系A,再满足关系B
规则4.2:外键或者取空值NULL,或者等于被参照关系中的主键的某个值.
---规则4.2是结论,通过两个例子去理解.
例1中的专业号是外键.对于参照关系(学生表)而言,学生可以没选专业(此时是NULL),如果选了专业,其专业号取值必须和被参照关系(专业表)中专业号在同一个域里(必须符合其中一个值).
例2中参照关系和被参照关系是同一个关系.如果班长没选出来,此项取值NULL.如果选出来了,则必有"班长学号"的取值和主键(学号)取值中的一个值相等.原因班长必是学生中的一员
一句话总结:外键取值优先,可以为NULL.
3.用户定义完整性规则
规则4.3 属性的取值应当满足用户定义的约束条件.
综上所述,三类完整性对应了3条规则.这是设计者提出的需求,且由SQL语言提供实现
本书P105最后一段:DBMS应该提供定义和检验这类完整性的机制(例如约束、触发器等).以便用统一方法来处理它们,而不应该由应用程序来承担这个功能.
---前面帖子中讲过应用程序(高级语言)有丰富的逻辑表达能力和数据控制能力,但是在和数据库交互中,他所做的事是把参数传入SQL,调用SQL函数(通常是SELECT),提取返回值.并不能在建立表和传入表数据时产生各种约束.所以实际上应用程序想承担这个功能都不行.
例4-1 参照完整性规则的变通
这里是对参照完整性的一点补充:
1)外键和主键可以不同名,只要值域相同
---笔者对此感到困惑.如果外键不同名岂不是会产生误会吗?所以尽量别这样做,保持同名.
2)依赖关系和参照关系可以是同一个关系
---这点前面已经表达过.注意,这里的外键不管是表示"先修"还是"后继",结果都是一样的(他的外键是PC#),PC#取值可以是NULL,或者是C#中的某个值.原因不管先修还是后继课程,都是课程的一种.
3)外键取值和第2)意思相同.
4.2.2MySQL提供的约束
包括了主键约束,唯一约束,检查约束,外键约束.
1.主键约束(PRIMARY KEY)
目的:值唯一,非空
添加方法:见本书P106,P107.推荐使用表级PRIMARY KEY约束.
/*表级主键约束*/
CREATE TABLE employee(
empno DECIMAL(2),
name VARCHAR(8),
age DECIMAL(3),
deptno DECIMAL(2),
CONSTRAINT pk_no PRIMARY KEY(empno)
);
调试:不输入empno,不能通过如下图所示
当输入正确的empno格式后,通过如下图所示
修改主键约束:创建表后添加主键约束,或者删除主键约束也可以,和表操作相同(ALTER语句)
2.唯一约束
唯一约束用于候选键的约束.
候选键本身没多大存在感,他的操作和主键约束差不多,注意可有一个空值(多个属性且无主键),
建立一个新表employee2,添加唯一约束,phone和name,即表示2个人可以用一个手机号码或者2人可重名
/*表级主键和唯一约束*/
CREATE TABLE employee2(
empno DECIMAL(2),
name VARCHAR(8),
age DECIMAL(3),
deptno DECIMAL(2),
phone VARCHAR(12),
CONSTRAINT pk_no PRIMARY KEY(empno),
CONSTRAINT emp_phone UNIQUE(phone,name)
);
以下是测试结果:
第5项可以添加是没想到的:两个键组成的唯一约束,两个输入NULL都可以,对于这个情况,一是用得不多不用纠结.二考虑在有主键存在的情况下,唯一约束可以都为空,因为有主键保证唯一性
3.检查约束
目的:通过检查输入表中的数据来维护用户定义的完整性.
关键词:CHECK指令
例4-5:建立employee表,限制age字段的值必须大于20且小于60.
CREATE TABLE employee2(
empno DECIMAL(2),
name VARCHAR(8),
age DECIMAL(3),
deptno DECIMAL(2),
phone VARCHAR(12),
CONSTRAINT pk_no PRIMARY KEY(empno),
CONSTRAINT age_CK CHECK(age>20 AND age<60)
);
输入一个不满足条件的年龄:18,以下是测试结果:
输入满足条件的年龄:22,以下是测试结果:
修改检查约束:创建表后添加检查约束,或者删除检查约束也可以,和表操作相同(ALTER语句)
4.外键约束
本书P109:外键约束涉及两个表,即主表和从表.从表是指外键所在的表,主表是指外键在另一张表中作为主键的表.
---这里的两个概念:主表和从表一定要区分清楚.像笔者这样记忆力不好的特别要注意别弄混了.
主表其实是前面说过的"被参照关系",从表是"参照关系".这里做两点理解:
1>从表中的外键值受主表限制,可以取NULL或主表中对应的值;
2>从表的外键值可以相同.
笔者在这里用两个表来说明主表和从表,记住这两个表,很容易对主表和从表做出判定:
学生表(主表) | 选课表(从表) | |||||||
学号(主键) | 姓名 | 性别 | 出生日期 | 课程号(主键) | 课程名 | 学号(外键) | 成绩 | |
1001 | 张三 | 男 | 1980/4/30 | 75001 | 电影鉴赏 | 1001 | 95 | |
1002 | 李四 | 男 | 1980/8/30 | 75002 | 中国古文学 | 1001 | 96 |
从表的外键值可以相同.在这里的表现就是张三选修了两门课
此外主表可以看成从表的"基石",从表外键取值必须从主表的主键值中选取(或者NULL)
主表主键操作对从表的影响
1)插入:无影响
2)修改:若从表中的外键值与主表中的主键值一样,则有影响
3)删除:同上,可能有影响
从表外键操作对完整性的影响
1)插入:受从表主键值的约束
2)修改:同上,受从表主键值的约束
3)删除:无影响
主表和从表重在理解,上面的几点不用刻意去记.
例4-6
建立两个表employee和department,实现两个表的外键约束,并指定级联更新和级联删除
CREATE TABLE department(
deptno DECIMAL(5),
dept_name VARCHAR(16),
CONSTRAINT dp_no PRIMARY KEY(deptno)
);
CREATE TABLE employee2(
empno DECIMAL(5) PRIMARY KEY,
ename VARCHAR(10) NOT NULL,
age DECIMAL(3),
deptno DECIMAL(5),
CONSTRAINT FK_ID FOREIGN KEY(deptno) REFERENCES department(deptno) ON UPDATE CASCADE,
CONSTRAINT FK_IG FOREIGN KEY(deptno) REFERENCES department(deptno) ON DELETE CASCADE
);
注意:这里把级联更新和级联删除放在一起.注意用CONSTRAINT给外键命名时,需要不同的名称,否则报错.
生成下面两个表
表1:department(主表)
表2:employee2(从表)
然后笔者进行了两步操作:
1.删除级联更新的外键约束
/*删除级联更新FK_IG*/
ALTER table employee2 DROP FOREIGN KEY FK_IG;
2.把department中的数据修改
刷新后NaviCat Premium lite17 崩溃了,重新打开后,表employee2内的数据发生了变化
级联更新发生了,但是把其他数据给删除了,原因暂时未知.
启示
先不管什么原因造成的,以此看出数据库操作要小心,及时做好备份.每一步操作都能回溯.
修正
重新建立employee2表如下:
CREATE TABLE employee2(
empno DECIMAL(5) PRIMARY KEY,
ename VARCHAR(10) NOT NULL,
age DECIMAL(3),
deptno DECIMAL(5),
CONSTRAINT FK_ID FOREIGN KEY(deptno) REFERENCES department(deptno) ON UPDATE CASCADE
);
生成数据
修改department表
关闭软件再打开软件,点开employee2表
修改成功
原因探寻
1.软件问题.这个笔者并不太熟,是可能原因
2. 是否只允许提交一个外键,多个外键冲突?
3.从语义上看cascade和set null有冲突.cascade和no action或许可以同时用.有机会可以试试
小结
数据库完整性规则和MySQL提供的约束的一些分析