【关于外键约束的一些常见问题】

本文介绍了在SQL Server中创建和管理外键约束的方法,并通过具体示例演示了常见操作及可能遇到的问题,如创建表时定义外键、修改现有表添加外键、删除外键约束等。

【关于外键约束的一些常见问题】

 

/********************************************************************

Author:js_szy

Date:2010-11-08

 

Version:

    Microsoft SQL Server 2005 - 9.00.1399.06 (Intel X86)

       Oct 14 2005 00:33:37

       Copyright (c) 1988-2005 Microsoft Corporation

       Developer Edition on Windows NT 5.1 (Build 2600: Service Pack 3)

 

********************************************************************/

--> 测试数据: [tb]

if OBJECT_ID('[tb]') is not null DROP TABLE [tb]

go

--> 测试数据: [ta]

if OBJECT_ID('[ta]') is not null DROP TABLE [ta]

go

 

CREATE TABLE [ta]

(

    id int PRIMARY KEY,

    name varchar(1)

)

 

CREATE TABLE [tb]

(

    id1 int CONSTRAINT fk_1 FOREIGN KEY REFERENCES  ta(id),

    name1 varchar(1)

   

)

 

INSERT INTO [ta]

SELECT 1,'a' UNION ALL

SELECT 2,'b'

 

INSERT INTO [tb]

SELECT 1,'q' UNION ALL

SELECT 1,'w' UNION ALL

SELECT 2,'s'

 

/*******************************************************************/

一、创建外键约束:

 

1、创建表时建外键约束:

 

    CREATE TABLE[tb]

    (

       id1 int CONSTRAINT fk_1 FOREIGN KEY REFERENCES  ta(id),

       name1 varchar(1)

      

    )

 

2、在已有表上创建约束

 

    ALTER TABLEtb ADD CONSTRAINT fk_1 FOREIGN KEY (id1) REFERENCES ta(id)

 

 

/*******************************************************************/

二、删除约束:

 

    ALTER TABLEtb DROP CONSTRAINT fk_1

/*******************************************************************/

三、下面介绍一下一些常见的错误:

 

1、先建子表

 

    /*

    错误信息

       消息1767,级别16,状态0,第1

       外键'FK__tb__id1__7814D14C' 引用了无效的表'ta'

       消息1750,级别16,状态0,第1

       无法创建约束。请参阅前面的错误消息。

 

    解决方法:

       先建主表

    */

 

2、先删主表

    /*

    错误信息:

       消息3726,级别16,状态1,第2

       无法删除对象'ta',因为该对象正由一个FOREIGN KEY 约束引用。

       消息2714,级别16,状态6,第3

       数据库中已存在名为'ta' 的对象。

 

    解决方法:

       先删子表

    */

 

3、插入子表数据,主表中不存在子表插入的键值

 

    INSERT INTO [tb]

    SELECT 5,'q'      -- 5 在主表中不存在

 

    /*

       错误信息:

           消息547,级别16,状态0,第1

          INSERT 语句与FOREIGN KEY 约束"FK__tb__id1__5D60DB10"冲突。该冲突发生于数据库"szy",表"dbo.ta", column 'id'

           语句已终止。

      

       解决方法:

           必须先插入主表,再插入子表

    */

 

4、先删除主表数据

 

    delete from ta where id=1

    /*

    错误信息:

       消息547,级别16,状态0,第68

       DELETE 语句与REFERENCE 约束"FK__tb__id1__047AA831"冲突。该冲突发生于数据库"szy",表"dbo.tb", column 'id1'

       语句已终止。

 

    解决方法:

       先删子表,再删主表

       delete from tb where id1=1

       delete from ta where id=1

    */

 

5、在已有数据的表上添加外键约束

    (如果表中存在主表与子表没有关联的键值,将报如下错误)

 

    ALTER TABLEtb ADD FOREIGN KEY (id1) REFERENCES ta(id) 

 

    /*

    消息547,级别16,状态0,第20

    ALTER TABLE 语句与FOREIGN KEY 约束"FK__tb__id1__23F3538A"冲突。该冲突发生于数据库"szy",表"dbo.ta", column 'id'

    */

 

/*******************************************************************/

 

总结:对有外键约束表的操作顺序,先建主,再建子。先删子,再删主。

 

 

<think>嗯,用户现在想了解MySQL约束的类型和使用方式。根据之前的对话,我之前已经介绍了约束的基本定义、使用方法、常见问题和管理方法,但用户现在需要更详细的信息,特别是类型和使用方式。 首先,我需要回顾之前提供的引用内容。引用[1]提到了约束错误,比如删除父表记录的错误,这说明约束的行为类型,比如RESTRICT、CASCADE等,可能是一个重点。引用[2]指出需要显式创建索引,而主会自动索引,这可能涉及到的索引要求。引用[3]展示了关联查询的例子,但用户现在关注的是约束类型和用法,所以这部分可能不太相关,但可以提到关联查询与的关系。 接下来,用户的问题明确要求约束的类型及用法。我需要将约束的类型分为不同类别。根据MySQL文档,约束的类型主要涉及操作类型(如ON DELETE和ON UPDATE的行为),可能还有约束的检查机(立即检查或延迟检查)。不过MySQL不支持延迟约束,所以可能不需要这部分。另约束的索引要求也是一个类型,比如必须显式创建索引。 在回答中,需要详细说明每种操作类型(RESTRICT、CASCADE、SET NULL、NO ACTION)的区别和适用场景,并结合示例。同,要强调索引的重要性,引用[2]中提到字段必须显式索引,这点需要重点说明,避免用户忽略导致性能问题或错误。 另,用户可能在使用方式上需要更多的语法示例,比如创建表定义不同行为,修改表添加的不同选项。还要注意常见问题,比如为什么需要索引,如何处理约束冲突等,结合之前的回答中的问题部分。 需要检查是否有遗漏的类型,比如是否存在其他约束相关的类型,例如MATCH FULL等,但MySQL可能不支持这些,所以可能不需要提及。确保回答的结构清晰,分点说明类型和用法,每个类型都有示例,这样用户更容易理解。 最后,用户可能需要知道如何选择合适的行为类型,比如在什么情况下使用CASCADE,何使用SET NULL,这可以在用法部分给出建议,帮助用户根据实际需求选择。 总结回答结构:先概述约束的核心作用,然后分类型详细说明(操作类型和索引类型),接着是具体的使用方法,包括创建、修改、删除,并强调索引的重要性,最后给出选择建议和常见问题。相关问题部分可以引导用户深入理解不同行为的影响和索引的必要性。</think>#### MySQL 约束的类型及用法详解 --- ##### 一、约束的核心类型 MySQL 约束的核心类型体现在 **操作行为控制** 和 **索引要求** 两方面: 1. **操作行为控制(`ON DELETE`/`ON UPDATE`)** 定义主表记录被删除或更新,子表数据的处理方式: - `RESTRICT`(默认) 阻止主表的删除/更新操作,若子表存在关联记录则直接报错[^1][^3]。 - `CASCADE` 级联操作:主表记录被删除/更新,**子表关联记录同步删除/更新**。 ```sql FOREIGN KEY (dept_id) REFERENCES dept(id) ON DELETE CASCADE -- 主表部门删除,子表员工记录同步删除 ``` - `SET NULL` 主表记录被删除/更新,**子表字段设为 `NULL`**(要求字段允许 `NULL`)。 ```sql FOREIGN KEY (dept_id) REFERENCES dept(id) ON DELETE SET NULL -- 主表部门删除,员工表的 dept_id 变为 NULL ``` - `NO ACTION` 与 `RESTRICT` 行为一致,仅在事务提交检查约束。 2. **索引要求** - **字段必须显式创建索引**(InnoDB 不会自动创建)[^2]。 - **主表字段必须是主或唯一索引**,确保关联值的唯一性。 --- ##### 二、约束的使用方式 ###### 1. **基础语法** ```sql -- 创建表定义 CREATE TABLE 子表 ( 子表字段 数据类型, INDEX 索引名 (字段), -- 必须显式创建索引 FOREIGN KEY (字段) REFERENCES 主表(主表字段) [ON DELETE 行为] [ON UPDATE 行为] ); -- 修改表添加 ALTER TABLE 子表 ADD CONSTRAINT 名称 FOREIGN KEY (字段) REFERENCES 主表(主表字段) [ON DELETE 行为] [ON UPDATE 行为]; ``` ###### 2. **完整示例** ```sql -- 主表(部门) CREATE TABLE dept ( id INT PRIMARY KEY, name VARCHAR(50) UNIQUE ); -- 子表(员工) CREATE TABLE emp ( id INT PRIMARY KEY, dept_id INT, INDEX idx_dept (dept_id), -- 显式创建索引 FOREIGN KEY (dept_id) REFERENCES dept(id) ON DELETE CASCADE ON UPDATE CASCADE ); ``` ###### 3. **行为选择建议** | 行为类型 | 适用场景 | |----------------|--------------------------------------------------------------------------| | `RESTRICT` | 需要严格保护主表数据,防止误删(如财务核心数据) | | `CASCADE` | 主从表数据强关联(如部门与员工,部门删除员工同步清除) | | `SET NULL` | 允许子表为空,且业务逻辑接受关联中断(如商品分类删除后商品暂无分类)| --- ##### 三、关注意事项 1. **索引缺失导致失效** 若子表未对字段创建索引,会引发以下问题: - 约束可能无法生效[^2] - 关联查询性能下降(如 `JOIN` 操作) 2. **循环依赖问题** 避免两个表互相设置,否则可能导致无法插入数据或删除表。 3. **名称全局唯一** 同一数据库名称不可重复,建议命名规则:`fk_子表_主表_字段`(如 `fk_emp_dept_id`)。 --- ##### 四、约束管理 ```sql -- 查看定义 SHOW CREATE TABLE emp; -- 删除约束 ALTER TABLE emp DROP FOREIGN KEY fk_emp_dept_id; -- 临禁用检查(批量导入数据使用) SET FOREIGN_KEY_CHECKS = 0; -- 导入操作... SET FOREIGN_KEY_CHECKS = 1; ``` ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值