您的位置:首页 > 数据库 > MySQL

mysql innodb 外键关联约束讲解

2013-03-28 21:52 218 查看
可通过查表信息查看外键的创建信息:Showcreate table tablename \G;

从mysql 3.23.44开始,innodb支持外键约束,跟Oracle基本相同,语法形式如下

[CONSTRAINTsymbol] FOREIGN KEY [id] (index_col_name, ...)

REFERENCEStbl_name (index_col_name, ...)

[ON DELETE{RESTRICT | CASCADE | SET NULL | NO ACTION}]

[ON UPDATE{RESTRICT | CASCADE | SET NULL | NO ACTION}]

ALTER TABLEyourtablename

ADD[CONSTRAINT symbol]FOREIGN KEY [id]
(index_col_name,...)

REFERENCES tbl_name (index_col_name,...)

[ON DELETE{RESTRICT | CASCADE | SET NULL | NO ACTION}]

[ON UPDATE{RESTRICT | CASCADE | SET NULL | NO ACTION}]

外键约束对子表的含义:

如果在父表中找不到该键的值,则不允许在子表上进行insert/update。

外键约束对父表的含义:

在父表上进行update/delete以更新或删除,在子表中有一条或多条对应匹配行的外键时,父表的行为取决于:在定义子表的外键时指定的onupdate/on delete子句, InnoDB支持5种方式, 分列如下

事件触发限制:

CASCADE: 从父表删除或更新且自动删除或更新子表中匹配的行。ONDELETE CASCADE和ON UPDATECASCADE都可用。在两个表之间,你不应定义若干在父表或子表中的同一列采取动作的ON
UPDATECASCADE子句。

SETNULL: 从父表删除或更新行,并设置子表中的外键列为NULL。如果外键列没有指定NOTNULL限定词,这就是唯一合法的。ON DELETE SET NULL和ON UPDATE SETNULL子句被支持。

NOACTION: 在ANSISQL-92标准中,NOACTION意味这不采取动作,就是如果有一个相关的外键值在被参考的表里,删除或更新主要键值的企图不被允许进行(Gruber,掌握SQL, 2000:181)。InnoDB拒绝对父表的删除或更新操作。

RESTRICT: 拒绝对父表的删除或更新操作。NOACTION和RESTRICT都一样,删除ON
DELETE或ON UPDATE子句。(一些数据库系统有延期检查,并且NOACTION是一个延期检查。在MySQL中,外键约束是被立即检查的,所以NOACTION和RESTRICT是同样的)。

SETDEFAULT: 这个动作被解析程序识别,但InnoDB拒绝包含ONDELETE SET DEFAULT或ON
UPDATE SET DEFAULT子句的表定义。

在已存在的表中创建外键

alter table 外键所在的表名 add constraint 外键名 foreign key(外键所在的列名)references 对应主键所在表名(主键所在列名);

alter table 外键所在的表名 add constraint 外键名 foreign key(外键所在的列名)references 对应主键所在表名(主键所在列名) ON DELETE CASCADE ONUPDATE NO ACTION;

删除外键

alter table tablename drop foreign keynamefk;

外键的作用:

保持数据一致性,完整性,主要目的是控制存储在外键表中的数据。使两张表形成关联,外键只能引用外表中的列的值!

例如:

a b两个表

a表中存有客户号,客户名称

b表中存有每个客户的订单

有了外键后

你只能在确信b表中没有客户x的订单后,才可以在a表中删除客户x

建立外键的前提:本表的列必须与外键类型相同(外键必须是外表主键)。

指定主键关键字:foreign key(列名)

引用外键关键字:references 外键表名(外键列名)

例子:

products 和serial是一对多的关系

serial.pid字段是外键,products.id字段是外表对应的主键

--

-- 表的结构`products`

--

DROP TABLE IFEXISTS `products`;

CREATE TABLE IFNOT EXISTS `products` (

`id`int(11) NOT NULL auto_increment,

`name`varchar(55),

PRIMARYKEY (`id`),

KEY`name` (`name`)

)ENGINE=InnoDB;

--

-- 表的结构`serial`

--

DROP TABLE IFEXISTS `serial`;

CREATE TABLE IFNOT EXISTS `serial` (

`id`int(11) NOT NULL auto_increment,

`name`varchar(55) ,

`pid`int(11) default NULL,

PRIMARYKEY (`id`),

KEY`name` (`name`),

KEY`pid` (`pid`),

CONSTRAINT `pidfk` FOREIGN KEY (`pid`) REFERENCES `products`(`id`) ONDELETENOACTION ONUPDATE CASCADE

) ENGINE=InnoDB;

//可以修改表添加约束

mysql>alter table `serial` add constraint `keyname` foreign key(`pid`)references products(`id`) on delete cascade on updatecascade;

其它

1,mysqldump在dump数据时,会加入外键信息

2, 也可以用SHOWTABLE STATUS FROM db_name LIKE 'tbl_name';查看外键信息,在comment列中

3,注意innodb中如果设置了lower_case_table_names,对外键的影响

4,在创建外键时,可以加入backtricks(反引号),将外键名,列名包括起来

5,如果是在mysql3.23.50之前版本,注意如果表上有外键或者作为父表被refer,不要使用alter table , createindex命令

6,Innodb要进行外键check时,需要在父或子表上加共享行级锁(shared rowlock),不是事务级

7,从mysql4.1.1开始,为了使reloaddumpfile更容易进行,mysqldump生成的文件自动添加了FOREIGN_KEY_CHECKS=0选项以禁止外键约束检查

对于早期版本,可以用下面方法达到同样目的

mysql> SET FOREIGN_KEY_CHECKS =0;

mysql> SOURCEdump_file_name

mysql> SET FOREIGN_KEY_CHECKS =1;

8, 在altertable或load data时,可能也需要进行上述设置以临时禁止外键约束检查

9,除非设置了FOREIGN_KEY_CHECKS = 0,Innodb禁止drop父表(被子表外键引用的表)

10,当设置FOREIGN_KEY_CHECKS =0后drop一个父子.

下次重新创建这个父表时,必须跟drop之前一样(正确的列/数据类型/被参照的列上必须有索引),否则系统会报1005 refer to errno150 (这一点前述测试中没有发现报错
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: