赞
踩
Foreign Key(外键)是数据库的一个很重要的概念。当两张表存在关联字段的时候,利用外键可以保证主表和从表的一致性和完整性。但是由于外键是Constraint,肯定会对表的新增删除修改产生性能的影响,所以到底使不使用,什么时候使用,该怎么用需要慎重考虑。
假设我们有张主表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’ 所以数据插入是没问题的。
结果发现是不行的,外键阻止我们这种错误的操作。都没这个user你怎么往它的账户上打钱?
比如我们试着删除’yf’这个user。
哈哈,不行吧? 除非你把子表关联的数据全部删除,你才能删除该条主表的数据。
同样,update操作也会因为外键限制操作失败,这里就不展示了。
参考
我们刚才讨论的情况,都是建立在
删除:从表记录不存在时,主表才可以删除。删除从表,主表不变
更新:从表记录不存在时,主表才可以更新。更新从表,主表不变
然而我们可以自定义外键的规则,比如我们删除了主表的某条数据,子表相应的数据都会被删除等。
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作用,我们再创建一个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;
。
但无论什么约束情况,主表不存在的主键子表也是不能插入相应的外键的,这是所有外键约束的基本原则。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。