欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

MySQL外键约束On Delete、On Update各取值的含义

先看On Delete属性,可能取值如上图为:No Action, Cascade,Set Null, Restrict属性。

当取值为No Action或者Restrict时,则当在父表(即外键的来源表)中删除对应记录时,首先检查该记录是否有对应外键,如果有则不允许删除。

当取值为Cascade时,则当在父表(即外键的来源表)中删除对应记录时,首先检查该记录是否有对应外键,如果有则也删除外键在子表(即包含外键的表)中的记录。

当取值为Set Null时,则当在父表(即外键的来源表)中删除对应记录时,首先检查该记录是否有对应外键,如果有则设置子表中该外键值为null(不过这就要求该外键允许取null)。

 

 

MySQL外键约束On Delete、On Update各取值的含义 - sujoe_2006 - 程序·思维·网摘

On Update是一样的?

当取值为No Action或者Restrict时,则当在父表(即外键的来源表)中更新对应记录时,首先检查该记录是否有对应外键,如果有则不允许更新。

 

当取值为Cascade时,则当在父表(即外键的来源表)中更新对应记录时,首先检查该记录是否有对应外键,如果有则也更新外键在子表(即包含外键的表)中的记录。

当取值为Set Null时,则当在父表(即外键的来源表)中更新对应记录时,首先检查该记录是否有对应外键,如果有则设置子表中该外键值为null(不过这就要求该外键允许取null)。

 

比如我有这样两张表:

tbluser用户表:

 

DROP TABLE IF EXISTS `filedb`.`tbluser`;

CREATE TABLE  `filedb`.`tbluser` (

  `UserID` varchar(50) NOT NULL COMMENT '主键',

  `UserName` varchar(40) NOT NULL COMMENT '用户姓名',

  `UserMail` varchar(50) NOT NULL COMMENT '用户邮箱',

  `UserPassword` varchar(50) NOT NULL COMMENT '密码',

  `UserType` tinyint(3) unsigned DEFAULT '0' COMMENT '默认为0,表示普通用户',

  `UserCreated` datetime DEFAULT '0000-00-00 00:00:00',

  PRIMARY KEY (`UserID`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

----------------------------------------------------------------------------------------------------------------

tblfile文件(用户的文件)表:

 

DROP TABLE IF EXISTS `filedb`.`tblfile`;

CREATE TABLE  `filedb`.`tblfile` (

  `FileID` int(10) unsigned NOT NULL AUTO_INCREMENT,

  `FileOwner` varchar(50) DEFAULT NULL COMMENT '外键,引用用户表',

  `FileName` varchar(200) NOT NULL COMMENT '文件原始名称',

  `FilePath` varchar(200) NOT NULL COMMENT '文件存放路径',

  `FileType` varchar(10) NOT NULL COMMENT '文件类型',

  `FileSubject` varchar(100) NOT NULL COMMENT '文件标题',

  `FileCreated` datetime DEFAULT '0000-00-00 00:00:00' COMMENT '创建时间',

  PRIMARY KEY (`FileID`),

  KEY `FK_tblfile_1` (`FileOwner`),

  CONSTRAINT `FK_tblfile_1` FOREIGN KEY (`FileOwner`) REFERENCES `tbluser` (`UserID`) ON DELETE SET NULL ON UPDATE CASCADE 

) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

-------------------------------------------------------------------------------------------------

上面可以看出FileOwner是文件表的外键,引用的是用户表的UserID。且这里外键约束设置为"ON DELETE SET NULL ON UPDATE CASCADE " 

现在用户表有记录(省略其他无关的字段):

UserID

ST001

,而文件表有记录

FileID   FileOwner

1          ST001

那么如果我删除用户表中ST001对应记录时,则根据ON DELETE SET NULL规则,文件表中FileOwner应该被设置为null,动手尝试后也确实如此;如果我将用户表中ST001改为ST003,则根据ON UPDATE CASCADE规则,文件表中FileOwner应该连锁设置为ST003,也的确如此。

 

外键的使用对于减少数据库冗余性,以及保证数据完整性和一致性有很大作用。

另外注意,如果两张表之间存在外键关系,则MySQL不能直接删除表(Drop Table) (不能删除主表,可以删除副表),而应该先删除外键,之后才可以删除。
 

Mysql 下,外键设置: 

on delete rule: 
1、RESTRICT:约束 
    如果存在从数据,不允许删除主数据。 
2、NO ACTION 
    如果存在从数据,不允许删除主数据。 
3、CASCADE:级联 
    删除主数据,顺便也删掉从数据。 
4、SET NULL 
    删除主数据,从数据外键的值设为NULL。 

on update rule: 
1、RESTRICT:约束 
    修改主数据中被关联的Field,如果有该主数据有从数据,不允许修改。 
2、NO ACTION 
    修改主数据中被关联的Field,如果有该主数据有从数据,不允许修改。 
3、CASCADE 
    修改主数据中被关联的Field,如果有该主数据有从数据,顺便一起修改从数据的外键值。 
4、SET NULL 
    修改主数据中被关联的Field,如果有该主数据有从数据,从数据的外键值设为NULL。 


NO ACTION和RESTRICT的区别:只有在及个别的情况下会导致区别,前者是在其他约束的动作之后执行,后者具有最高的优先权执行。

来自 http://xiejielin.iteye.com/blog/1233532


来自 http://blog.163.com/sujoe_2006/blog/static/3353151201181654445246/

在MySQL 3.23.44版本后,InnoDB引擎类型的表支持了外键约束。
外键的使用条件:
1.两个表必须是InnoDB表,MyISAM表暂时不支持外键(据说以后的版本有可能支持,但至少目前不支持);
2.外键列必须建立了索引,MySQL 4.1.2以后的版本在建立外键时会自动创建索引,但如果在较早的版本则需要显示建立; 
3.外键关系的两个表的列必须是数据类型相似,也就是可以相互转换类型的列,比如int和tinyint可以,而int和char则不可以;

外键的好处:可以使得两张表关联,保证数据的一致性和实现一些级联操作;

外键的定义语法:
[CONSTRAINT symbol] FOREIGN KEY [id] (index_col_name, ...)
    REFERENCES tbl_name (index_col_name, ...)
    [ON DELETE {RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT}]
    [ON UPDATE {RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT}]
该语法可以在 CREATE TABLE 和 ALTER TABLE 时使用,如果不指定CONSTRAINT symbol,MYSQL会自动生成一个名字。
ON DELETE、ON UPDATE表示事件触发限制,可设参数:
RESTRICT(限制外表中的外键改动)
CASCADE(跟随外键改动)
SET NULL(设空值)
SET DEFAULT(设默认值)
NO ACTION(无动作,默认的)

搞个例子,简单演示一下使用,做dage和xiaodi两个表,大哥表是主键,小弟表是外键:
建表:

 1CREATE TABLE `dage` (
 2  `id` int(11NOT NULL auto_increment,
 3  `name` varchar(32default '',
 4  PRIMARY KEY  (`id`)
 5) ENGINE=InnoDB DEFAULT CHARSET=latin1;
 6
 7CREATE TABLE `xiaodi` (
 8  `id` int(11NOT NULL auto_increment,
 9  `dage_id` int(11default NULL,
10  `name` varchar(32default '',
11  PRIMARY KEY  (`id`),
12  KEY `dage_id` (`dage_id`),
13  CONSTRAINT `xiaodi_ibfk_1` FOREIGN KEY (`dage_id`) REFERENCES `dage` (`id`)
14) ENGINE=InnoDB DEFAULT CHARSET=latin1;

插入个大哥:
1mysql> insert into dage(name) values('铜锣湾');
2Query OK, 1 row affected (0.01 sec)
3mysql> select * from dage;
4+----+--------+
5| id | name   |
6+----+--------+
7|  1 | 铜锣湾 |
8+----+--------+
91 row in set (0.00 sec)

插入个小弟:
1mysql> insert into xiaodi(dage_id,name) values(1,'铜锣湾_小弟A');
2Query OK, 1 row affected (0.02 sec)
3
4mysql> select * from xiaodi;
5+----+---------+--------------+
6| id | dage_id | name         |
7+----+---------+--------------+
8|  1 |       1 | 铜锣湾_小弟A |
9+----+---------+--------------+

把大哥删除:
1mysql> delete from dage where id=1;
2ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`bstar/xiaodi`, CONSTRAINT `xiaodi_ibfk_1` FOREIGN KEY (`dage_id`) REFERENCES `dage` (`id`))


提示:不行呀,有约束的,大哥下面还有小弟,可不能扔下我们不管呀!

插入一个新的小弟:

1mysql> insert into xiaodi(dage_id,name) values(2,'旺角_小弟A');              
2ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`bstar/xiaodi`, CONSTRAINT `xiaodi_ibfk_1` FOREIGN KEY (`dage_id`) REFERENCES `dage` (`id`))
3


提示:小子,想造反呀!你还没大哥呢!

把外键约束增加事件触发限制:

 1mysql> show create table xiaodi;
 2
 3  CONSTRAINT `xiaodi_ibfk_1` FOREIGN KEY (`dage_id`) REFERENCES `dage` (`id`)
 4
 5mysql> alter table xiaodi drop foreign key xiaodi_ibfk_1; 
 6Query OK, 1 row affected (0.04 sec)
 7Records: 1  Duplicates: 0  Warnings: 
 8mysql> alter table xiaodi add foreign key(dage_id) references dage(id) on delete cascade on update cascade;
 9Query OK, 1 row affected (0.04 sec)
10Records: 1  Duplicates: 0  Warnings: 0

再次试着把大哥删了:
1mysql> delete from dage where id=1;
2Query OK, 1 row affected (0.01 sec)
3
4mysql> select * from dage;
5Empty set (0.01 sec)
6
7mysql> select * from xiaodi;
8Empty set (0.00 sec)



得,这回对应的小弟也没了,没办法,谁让你跟我on delete cascade了呢!

例子说明的应该蛮清楚了吧,其他功能对应手册自己实践吧!:-)

来自 http://www.cppblog.com/wolf/articles/69089.html

 

On Delete和On Update都有Restrict,No Action, Cascade,Set Null属性。现在分别对他们的属性含义做个解释。

ON DELETE

restrict(约束):当在父表(即外键的来源表)中删除对应记录时,首先检查该记录是否有对应外键,如果有则不允许删除。

no action:意思同restrict.即如果存在从数据,不允许删除主数据。

cascade(级联):当在父表(即外键的来源表)中删除对应记录时,首先检查该记录是否有对应外键,如果有则也删除外键在子表(即包含外键的表)中的记录。

set null:当在父表(即外键的来源表)中删除对应记录时,首先检查该记录是否有对应外键,如果有则设置子表中该外键值为null(不过这就要求该外键允许取null)

ON UPDATE

restrict(约束):当在父表(即外键的来源表)中更新对应记录时,首先检查该记录是否有对应外键,如果有则不允许更新。

no action:意思同restrict.

cascade(级联):当在父表(即外键的来源表)中更新对应记录时,首先检查该记录是否有对应外键,如果有则也更新外键在子表(即包含外键的表)中的记录。

set null:当在父表(即外键的来源表)中更新对应记录时,首先检查该记录是否有对应外键,如果有则设置子表中该外键值为null(不过这就要求该外键允许取null)。

注:NO ACTION和RESTRICT的区别:只有在及个别的情况下会导致区别,前者是在其他约束的动作之后执行,后者具有最高的优先权执行。

来自 http://www.2cto.com/database/201508/436109.html

普通分类: