MySql 外键约束 FOREIGN KEY REFERENCES 之 空、RESTRICT、NO ACTION、CASCADE、SET NULL 等类型分析和作用解读

本文详细介绍了MySQL中外键约束的工作原理及其对子表和父表的意义。解释了不同行为(如CASCADE、SET NULL、NO ACTION等)在外键约束中的作用,并提供了关于MySQL与SQL标准差异的说明。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

主表,从表【MySql】

空、RESTRICTNO ACTION

删除:从表记录不存在时,主表才可以删除。删除从表,主表不变

更新:从表记录不存在时,主表才可以更新。更新从表,主表不变

CASCADE

删除:删除主表时自动删除从表。删除从表,主表不变

更新:更新主表时自动更新从表。更新从表,主表不变

SET NULL

删除:删除主表时自动更新从表值为NULL。删除从表,主表不变

更新:更新主表时自动更新从表值为NULL。更新从表,主表不变


==================================================================================================================================


外键约束对子表的含义:

  如果在父表中找不到候选键,则不允许在子表上进行insert/update

 

外键约束对父表的含义:

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

 

  . cascade方式

   在父表上update/delete记录时,同步update/delete掉子表的匹配记录

   On delete cascade从mysql3.23.50开始可用; onupdate cascade从mysql4.0.8开始可用

 

  . set null方式

   在父表上update/delete记录时,将子表上匹配记录的列设为null

   要注意子表的外键列不能为notnull

   On delete set null从mysql3.23.50开始可用; onupdate set null从mysql4.0.8开始可用

 

  . No action方式

   如果子表中有匹配的记录,则不允许对父表对应候选键进行update/delete操作

   这个是ANSISQL-92标准,从mysql4.0.8开始支持

 

  . Restrict方式

   同noaction, 都是立即检查外键约束

 

  . Set default方式

   解析器认识这个action,但Innodb不能识别,不知道是什么意思...

【 注意】:trigger不会受外键cascade行为的影响,即不会解发trigger

 

在mysql中,与SQL标准相违背的三点

1.       如果在父表中有多个key值相同,那么在进行外键check时,会当成有相同key值的其他行不存在;比如当定义了一个restrict行为外键时,一个子表行对应到多个父表行(具有相同key值),Innodb不允许删除父表上的所有这些行

 

2.       父子表是同一个表,自我参照时不允许指定onupdate cascade, on update set null

从mysql4.0.13开始,允许同一个表上的on delete set null

从mysql4.0.21开始,允许同一个表上的on delete cascade

但级联层次不能超出15

 

3, Innodb在检查unique,constraint约束时,是rowby row而不是语句或事务结束;

  SQL标准中对constraint的检查是在语句执行完成时。

【详解+示例,请参考:http://www.cnblogs.com/discuss/articles/1862244.html】


<think>嗯,用户这次想深入了解数据库更新操作时的不同选项选择依据。看来用户在使用MySQL数据库时遇到了约束的行为选择问题,这在实际数据库设计中确实是个关决策点。从用户提供的引用材料看,ta已经掌握了基本概念(CASCADE/NOACTION/RESTRICT/SETNULL的定义),但需要更落地的场景化建议。用户可能是位中阶开发者——既不会问基础定义,又没提出特定业务场景,说明ta需要的是通用性设计原则。注意到用户特别强调“更新操作”时的选择依据(而非删除),这个细节很重要。很多资料着重讲DELETE场景,但UPDATE时的行为同样关。比如电商系统的SKU编码更新时,关联订单明细该如何处理?最核心的设计矛盾点其实就两个:数据完整性业务逻辑合理性。RESTRICTNOACTION偏向保守派(保数据),CASCADESETNULL偏向激进派(保业务)。用户可能正面临这样的权衡:-财务系统肯定优先数据一致(选RESTRICT)-内容管理系统可以考虑SETNULL(允许标签失效时不连坐文章)具体到更新操作的特殊性,需要提醒用户注意:UPDATE可能触发比DELETE更隐蔽的级联影响。比如部门编号从10改为20时:-CASCADE会把所有员工关联更新(适合编码标准化场景)-SETNULL会使员工dept_id悬(除非配套触发器否则不建议)用户没提具体数据库类型,但引用全是MySQL。要补充说明:不同DBMS对NOACTION实现有差异(标准SQL中本不允许延迟检查)。另需要警告InnoDB里使用SETNULL的前提条件(字段必须允许NULL)——这点引用[3]提到过,但用户可能没注意。最后考虑用案例驱动的方式回应可能效果更好。比如:-电商商品类目更新(适合CASCADE:保证SKU始终可溯源)-用户注销账号(适合SETNULL:保留订单但解除关联)等等,用户引用里有个矛盾点:引用[2]说NOACTION是默认行为,但引用[5]说等同于RESTRICT。这需要明确:在MySQL中,NOACTION实际会被重定义为RESTRICT行为(与SQL标准不同)。必须帮用户厘清这个常见误区。</think> 在数据库设计中,约束更新行为的选择需基于**数据完整性要求****业务逻辑**。以下是 MySQL 更新操作 (`ON UPDATE`) 的选择依据场景详解: --- ### **四大行为对比** | 行为 | 更新时的动作 | 适用场景 | 注意事项 | |------|--------------|----------|----------| | **`CASCADE`** | 主表更新主值时,**自动更新从表的值** | 强关联数据(如:部门编号 `dept_id` 全局同步) | 慎用!可能意修改大量数据 | | **`SET NULL`** | 主表更新主时,**从表设为 `NULL`** | 非强依赖关系(如:用户部门撤销时保留用户记录) | 从表字段必须允许 `NULL` | | **`RESTRICT`** | **阻止主表更新**(若从表存在关联记录) | 禁止变更核心主(如:订单号不可修改) | MySQL 中效果同 `NO ACTION` | | **`NO ACTION`** | 检查关联记录后执行更新(默认行为) | 需业务层控制一致性的场景 | 实际行为等价于 `RESTRICT` [^1][^5] | --- ### **选择依据与场景** 1. **`CASCADE`(级联更新)** - **场景**:主值作为业务标识符且需全局同步 ```sql -- 示例:修改部门ID时,自动更新所有员工的部门ID ALTER TABLE employee ADD FOREIGN KEY (dept_id) REFERENCES department(id) ON UPDATE CASCADE; ``` - **风险点**:若主被多次修改,可能引发不可控的连锁更新 [^2][^5]。 2. **`SET NULL`(置)** - **场景**:主表主变更时需保留从表历史记录 ```sql -- 示例:商品分类ID更新后,原有商品分类暂时置 ALTER TABLE product ADD FOREIGN KEY (category_id) REFERENCES category(id) ON UPDATE SET NULL; ``` - **要求**:字段必须未定义 `NOT NULL` 约束 [^3][^5]。 3. **`RESTRICT`/`NO ACTION`(禁止更新)** - **场景**:核心主不可变更(如支付流水号、合同编号) ```sql -- 示例:禁止修改已关联订单的用户ID ALTER TABLE orders ADD FOREIGN KEY (user_id) REFERENCES user(id) ON UPDATE RESTRICT; -- 或 NO ACTION ``` - **效果**:直接报错阻止更新,强制业务层处理关联数据 [^1][^5]。 --- ### **决策流程图** ```mermaid graph TD A[主表主是否需要更新?] --> B{从表是否必须跟随更新?} B -- 是 --> C[使用 CASCADE] B -- 否 --> D{允许从表?} D -- 是 --> E[使用 SET NULL] D -- 否 --> F[使用 RESTRICT/NO ACTION] ``` --- ### **关实践建议** 1. **关业务主**(如订单号、用户ID)优先选 `RESTRICT/NO ACTION`,避免意修改。 2. **层级关系数据**(如组织架构)可选 `CASCADE`,但需测试级联性能。 3. **历史数据保留**场景用 `SET NULL` + 额日志表记录变更。 4. **慎用组合行为**:`ON UPDATE CASCADE + ON DELETE SET NULL` 可能导致数据状态混乱 [^4][^5]。 > 引用示例:若在财务系统中修改账户编号,必须用 `RESTRICT` 确保关联交易记录不被自动修改,否则破坏审计追溯 [^5]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值