学习目标
- 掌握外键约束的添加方法
- 知道外键约束字段的添加及删除规则
1.多表查询概述
l实际开发中,一个项目通常需要很多张表才能完成。
l例如:一个商城项目就需要分类表(category)、商品表(products)、订单表(orders)等多张表。且这些表的数据之间存在一定的关系,接下来我们将在单表的基础上,一起学习多表方面的知识。
一对多关系:
常见实例:客户和订单,分类和商品,部门和员工。
一对多建表原则:在从表(多方)创建一个字段,字段作为外键指向主表(一方)的主键。
2.外键约束
2.1外键约束的定义
现在我们有两张表“分类表”和“商品表”
为了表明商品属于哪个分类,通常情况下,==我们将在商品表上添加一列,用于存放分类cid的信息==,此列称为:外键
此时“分类表==category”称为:主表==,“cid”我们称为主键。“商品表==products”称为:从表==,category_id称为外键。我们通过主表的主键和从表的外键来描述主外键关系,呈现就是==一对多关系==。
外键特点:
从表外键的值是对主表主键的引用。
从表外键类型,必须与主表主键类型一致。
举例:
上述表中,product表中的两条记录中的商品,都属于汽车分类。
category分类表,为唯一方,也就是主表,必须提供主键cid
products商品表,为多方,也就是从表,必须提供外键category_id
2.2绑定外键约束
为了我们可以更加清楚的体现商品表与分类表之间的联系,我们准备以下两张表,并建立外键关联关系:
绑定外键约束的格式如下:
在创表语句后添加:CONSTRAINT FOREIGN KEY (外键字段) REFERENCES 主表名(主键)
# 创建分类表CREATETABLEcategory( cid VARCHAR(32) PRIMARY KEY, cname VARCHAR(100) #分类名称); # 商品表CREATETABLEproducts ( pid VARCHAR(32) PRIMARY KEY, nameVARCHAR(40), price DOUBLE, category_id VARCHAR(32), # CONSTRAINT 约束# REFERENCES 参考CONSTRAINTFOREIGNKEY(category_id) REFERENCEScategory(cid) # 添加约束); # 查看表结构# 主表不需要进行任何操作,从表在表内设置外键字段,绑定主表主键即可DESC products; DESC category;
此时,主表结构为:
从表结构为:
外键约束绑定成功。
2.3外键约束检测
插入数据
接下来,我们向分类(category)表中添加数据记录。
INSERTINTOcategory(cid ,cname) VALUES(\'c001\',\'服装\');
向商品表添加普通数据,没有外键数据,默认为null
INSERTINTOproducts (pid,pname) VALUES(\'p001\',\'土豆\');
然后向商品(product)表中添加数据记录,外键信息填写刚才插入的主表主键的值”c001“
INSERTINTOproducts (pid ,pname ,category_id) VALUES(\'p002\',\'夹克\',\'c001\');
思考:如果在从表中插入的外键值,在主表中不存在会怎样? 我们来试一下:
INSERTINTOproducts VALUES(\'p003\', \'坦克\', 1200000, \'c002\');
此时将会报错,错误信息为:Cannot add or update a child row: a foreign key constraint fails (test01.products, CONSTRAINTproducts_ibfk_1FOREIGN KEY (category_id) REFERENCEScategory(cid))。
得出结论:==当我们引用的外键,在主表主键中没有相同的值,则不能插入,但是可以插入空值==。
删除数据
我们将分类(category)表中的’c001‘数据进行删除
DELETEFROMcategoryWHEREcid = \'c001\';
此时将会报错,错误信息为Cannot delete or update a parent row: a foreign key constraint fails (test01.products, CONSTRAINTproducts_ibfk_1FOREIGN KEY (category_id) REFERENCEScategory(cid))。
为什么会出现这种情况呢??
我们再尝试一下,先将商品(product)表中,引用主表中该条数据的记录删除。
DELETEFROMproducts WHEREpid = \'002\';
删除后,此时没有任何从表记录引用主表的c001分类,我们再次尝试删除分类(category)表中的’c001‘数据。
DELETEFROMcategoryWHEREcid = \'c001\';
删除成功。
由此我们得出结论:==如果要删除主表中的记录,需要先将从表中所有引用该数据的记录删除或者修改为引用其他记录==。
2.4外键约束的优点
- ==在插入数据时,保证了数据的准确性==
- ==在删除数据时,保证了数据的完整性==
3.小结
- 实际开发中,一个项目通常需要很多张表才能完成。
- 一对多建表原则:在从表(多方)创建一个字段,字段作为外键指向主表(一方)的主键。
- 从表外键的值是对主表主键的引用。
- 从表外键类型,必须与主表主键类型一致。
- 从表中引用了主表中的数据,主表中数据不可被删除。
- 主表中没有数据,从表外键也无法被插入。
- 外键约束的优点:
- 在插入数据时,保证了数据的准确性
- 在删除数据时,保证了数据的完整性