【数据库基础】Foreign Key的使用及其优缺点
2018-03-27 20:08
218 查看
Foreign Key(外键)是数据库的一个很重要的概念。当两张表存在关联字段的时候,利用外键可以保证主表和从表的一致性和完整性。但是由于外键是Constraint,肯定会对表的新增删除修改产生性能的影响,所以到底使不使用,什么时候使用,该怎么用需要慎重考虑。
使用外键的优缺点
我们希望以id这个字段作为别的表的外键关联一张子表balance。 balance表记录着user的账户余额以及币种。表结构如下
这里的uid就是user表的id字段。
我们可以通过
或者如果balance表已经建好了,通过alter语句来添加外键。
值得注意的是:
1. 外键字段在创建的时候就应该与主表的类型完全一致(长度啊等),否则创建外键会报错
2. 外键创建中关键字的references不是reference, 有一个字母s。
3. 主表子表必须都是InnoDB的表!
我们来看一下balance表是否创建好了外键
看到
等一下,注意到了没? 由于创建了外键,mysql自动的为uid字段设置了索引。。 这点也需要了解一下。。
接下来我们来看外键的作用。。。
uid=1和2的情况对应了user表中’yf’和’huangxiang’ 所以数据插入是没问题的。
结果发现是不行的,外键阻止我们这种错误的操作。都没这个user你怎么往它的账户上打钱?
哈哈,不行吧? 除非你把子表关联的数据全部删除,你才能删除该条主表的数据。
同样,update操作也会因为外键限制操作失败,这里就不展示了。
https://my.oschina.net/sallency/blog/465079
我们刚才讨论的情况,都是建立在
删除:从表记录不存在时,主表才可以删除。删除从表,主表不变
更新:从表记录不存在时,主表才可以更新。更新从表,主表不变
然而我们可以自定义外键的规则,比如我们删除了主表的某条数据,子表相应的数据都会被删除等。
NULL、RESTRICT、NO ACTION
删除:从表记录不存在时,主表才可以删除。
更新:从表记录不存在时,主表才可以更新。
CASCADE
删除:删除主表时自动删除从表。
更新:更新主表时自动更新从表。
SET NULL
删除:删除主表时自动更新从表值为NULL。
更新:更新主表时自动更新从表值为NULL。
如果子表试图创建一个在父表中不存在的外键值,InnoDB会拒绝任何INSERT或UPDATE操作。如果父表试图UPDATE或者DELETE任何子 表中存在或匹配的外键值,最终动作取决于外键约束定义中的
然后复制balance表已有的数据到tongbu_balance表
然后我们试着删除主表中的’huangxiang’ …
删除前两表的状态如下
↓↓↓↓↓↓↓↓↓↓删除后↓↓↓↓↓↓↓↓↓↓
子表中’huangxiang’对应的uid=2的数据全部也跟着删除了…
同样当我们UPDATE主表的时候,子表也会跟着UPDATE.. 这里就不做演示了。。
当我们想自定义规则的时候,注意用
1)父表更新时子表也更新,父表删除时如果子表有匹配的项,删除失败;
2)父表更新时子表也更新,父表删除时子表匹配的项也删除。
前一种情况,在外键定义中,我们使用
但无论什么约束情况,主表不存在的主键子表也是不能插入相应的外键的,这是所有外键约束的基本原则。
使用外键的优缺点
如何建立外键
假设我们有张主表user表,表结构如下我们希望以id这个字段作为别的表的外键关联一张子表balance。 balance表记录着user的账户余额以及币种。表结构如下
这里的uid就是user表的id字段。
我们可以通过
create table balance( ... foreign key(uid) references user(id) ) ...
或者如果balance表已经建好了,通过alter语句来添加外键。
alter table balance add foreign key(uid) references user(id);
值得注意的是:
1. 外键字段在创建的时候就应该与主表的类型完全一致(长度啊等),否则创建外键会报错
2. 外键创建中关键字的references不是reference, 有一个字母s。
3. 主表子表必须都是InnoDB的表!
我们来看一下balance表是否创建好了外键
show create table balance;
看到
CONSTRAINT `balance_ibfk_1` FOREIGN KEY (`uid`) REFERENCES `user` (`id`)看来是创建好了。
等一下,注意到了没? 由于创建了外键,mysql自动的为uid字段设置了索引。。 这点也需要了解一下。。
接下来我们来看外键的作用。。。
如何利用外键约束
我们试着往balance表中添加几条数据uid=1和2的情况对应了user表中’yf’和’huangxiang’ 所以数据插入是没问题的。
接下来我们插入主表不存在的uid试试
结果发现是不行的,外键阻止我们这种错误的操作。都没这个user你怎么往它的账户上打钱?
如果我们删除子表中已经关联上的主表数据呢
比如我们试着删除’yf’这个user。哈哈,不行吧? 除非你把子表关联的数据全部删除,你才能删除该条主表的数据。
同样,update操作也会因为外键限制操作失败,这里就不展示了。
外键进阶
参考https://my.oschina.net/sallency/blog/465079
我们刚才讨论的情况,都是建立在
删除:从表记录不存在时,主表才可以删除。删除从表,主表不变
更新:从表记录不存在时,主表才可以更新。更新从表,主表不变
然而我们可以自定义外键的规则,比如我们删除了主表的某条数据,子表相应的数据都会被删除等。
NULL、RESTRICT、NO ACTION
删除:从表记录不存在时,主表才可以删除。
更新:从表记录不存在时,主表才可以更新。
CASCADE
删除:删除主表时自动删除从表。
更新:更新主表时自动更新从表。
SET NULL
删除:删除主表时自动更新从表值为NULL。
更新:更新主表时自动更新从表值为NULL。
如果子表试图创建一个在父表中不存在的外键值,InnoDB会拒绝任何INSERT或UPDATE操作。如果父表试图UPDATE或者DELETE任何子 表中存在或匹配的外键值,最终动作取决于外键约束定义中的
ON UPDATE和
ON DELETE选项。InnoDB支持5种不同的动作,如果没有指定
ON DELETE或者
ON UPDATE,默认的动作为RESTRICT也就是我们上面的例子
cascade关键字
为了测试cascade作用,我们再创建一个tongbu_balance表.然后复制balance表已有的数据到tongbu_balance表
insert into tongbu_balance select * from balance;
然后我们试着删除主表中的’huangxiang’ …
删除前两表的状态如下
↓↓↓↓↓↓↓↓↓↓删除后↓↓↓↓↓↓↓↓↓↓
子表中’huangxiang’对应的uid=2的数据全部也跟着删除了…
同样当我们UPDATE主表的时候,子表也会跟着UPDATE.. 这里就不做演示了。。
当我们想自定义规则的时候,注意用
ON UPDATE/DELETE 规则这样的语法限定外键就好了。。。
组合使用
外键约束使用最多的两种情况无外乎:1)父表更新时子表也更新,父表删除时如果子表有匹配的项,删除失败;
2)父表更新时子表也更新,父表删除时子表匹配的项也删除。
前一种情况,在外键定义中,我们使用
ON UPDATE CASCADE ON DELETE RESTRICT;后一种情况,可以使用
ON UPDATE CASCADE ON DELETE CASCADE;。
但无论什么约束情况,主表不存在的主键子表也是不能插入相应的外键的,这是所有外键约束的基本原则。
相关文章推荐
- Delphi基础:回调函数及其使用
- AppFramework1.0数据库访问组件使用说明(四)基础数据类型
- 使用SQL Server 数据库基础
- 使用SQL Server 数据库基础
- 数据库外键的使用以及优缺点
- 数据库:使用SQL Server 数据库基础
- Delphi基础:回调函数及其使用
- SQL点滴17—使用数据库引擎存储过程,系统视图查询,DBA,BI开发人员必备基础知识
- 黑马程序员 数据库一些基础使用
- 浅谈工作中曾经使用的数据库及其体验
- l数据库基础前四章总结(增删改查基础命令语句的的使用
- 数据库外键的使用以及优缺点
- 数据库外键的使用以及优缺点
- 一步一步教你使用AgileEAS.NET基础类库进行应用开发-基础篇-ORM访问器及其配置
- C#分析数据库结构,使用XSL模板自动生成代码 - 清清月儿 .NET万花筒 Asp.net技术 Asp.net教程 Asp.net源码 Asp.net基础 Asp.net控件 Asp.net入门 - CSDNBlog
- 使用LINQ实现对数据库单张表的基础增删改查操作
- 使用数据源连接数据库 和 使用驱动类包连接数据库 相比有什么优缺点?
- 数据库外键的使用以及优缺点
- java基础-使用jdbc访问数据库
- DB2 基础: 使用重定向恢复克隆 DB2 数据库