[TOC]
*****
约束是一种简单地强加于表中一列或多列的限制,约束有以下几种不同的类型。\*\*主键约束 \*\*
标志一列或多列,并保证其值在表内的唯一性。**外键约束**指该列引用的是其他表的主键,在其他表主键列进行更新或删除时要一同更新或删除。
用外键和其他表中的对应主键关联,可以确定其他表中的唯一一条记录。
**唯一约束**限制一列或多列的值,保证其在表内的唯一性(主键约束是一种特殊类型的唯一约束)。
**检查约束**限制一列的可用值范围
如果服务器允许只修改 customer表中的客户 ID 而不改变 account 表中的同一个 ID,那么最终结果就是账户不再指向合法的客户记录(所谓孤儿行)。不过,有了合适的主键和外键约束后,服务器就可以在试图修改或删除被其他表引用的数据时要么抛出一个错误,要么将这些改变传播到其他表(稍后会作更多讨论)
## 13.2.1 创建约束
**创建约束**
指定了 product\_cd 列作为product表的主键,还指定了 product\_type\_cd 列作为product\_type 表的外键
![](https://box.kancloud.cn/ddfa8f37afd50e4a6cc2dbbf3d402ddd_689x214.png)
\*\* 通过 alter table 语句添加主键约束和外键约束\*\*
![](https://box.kancloud.cn/622f45fde3f99c323e64f68b8882645a_701x123.png)
**删除主键约束或者外键约束**
![](https://box.kancloud.cn/626c530bce5402619df9ee6485cf2269_391x113.png)
*****
## 13.2.2 约束与索引
![](https://box.kancloud.cn/8e051a189ed58ad3da6ff105e1679296_790x182.png)
## 13.2.3 级联约束
有了合适的外键约束后,如果插入新行或者修改行而导致表中的外键列并不匹配父表中主键列的值,那么服务器会抛出一个错误。
product\_type是product的父表, product\_type\_cd列在两表中作为主外键。
![](https://box.kancloud.cn/831388d23c75feeeb9c6ad4a21e81405_595x690.png)
下面试图执行的语句:
![](https://box.kancloud.cn/f25fde0e261878559a6b0e8c4261749d_996x235.png)
如果父行没有相应的值,外键约束不允许更改子行
product\_type 表 中 没 有 哪 一 行 的 product\_type\_cd 列值为 XYZ,所以服务器的更新是不会成功的。
*****
![](https://box.kancloud.cn/6e06da614d1fea2885f15e94cf3973e4_975x224.png)
因为 product 表中存在子行的 product\_type\_cd 列值为LOAN,所以不允许父行将LOAN变为XYZ。
**级联更新**
可以命令服务器帮助父行将主键变化传播到所有子行的外键,这样就保证了数据的完整性。用on update cascade 语句
1. 先删除原有约束
2. 再增加级联更新约束
![](https://box.kancloud.cn/306409fc93faeca49ef775b52dfbb5f8_1050x637.png)
再次执行update语句:
![](https://box.kancloud.cn/c65c5323e01325e362d36b7272fd57db_585x157.png)
用select看两张表中的记录,product\_type 表的改变已经传播到了 product 表。
**级联删除**
如果 product\_type 表中的行被删除, product 表中的子行也将被删除
![](https://box.kancloud.cn/2fc3c5a2d9b5a5435085f9ca0460006a_973x467.png)
当 product\_type 表中的一行被更新时,服务器将更新 product 表中的子行