MySQL 自我外键

MySQL 自我外键

MySQL自我外键是MySQL关系数据库中一种特殊的外键约束,它可以将表中的一个或多个列自身设置为外键。当一张表中的数据需要引用这张表中同一列的另一行时,可以使用MySQL自我外键来实现。

阅读更多:MySQL 教程

MySQL自我外键的适用场景

  1. 父子级表结构

在一些父子级表结构中,子表的每一行必须关联到该表的父级表中自己本身所属行。比如,department表,包含一列父级部门ID,和一列当前部门ID,在该表的数据需要形成一棵树的时候,使用自我外键可以直接建立父子级关系约束。

-- department表结构
CREATE TABLE department (
  id INT PRIMARY KEY,
  name VARCHAR(255),
  parent_id INT
);

-- 在department表上创建自我外键
ALTER TABLE department ADD CONSTRAINT fk_department_self FOREIGN KEY (parent_id) REFERENCES department (id);
  1. 朋友关系表结构

在一些朋友关系表结构中,用户可以将自己与其他用户建立好友关系,好友关系可以是单向的,也可以是双向的。使用自我外键可以直接在一张表中建立这种朋友关系的限制。

-- user表结构
CREATE TABLE user (
  id INT PRIMARY KEY,
  name VARCHAR(255)
);

-- friend表结构
CREATE TABLE friend (
  user_id INT,
  friend_user_id INT,
  PRIMARY KEY (user_id, friend_user_id),
  FOREIGN KEY (user_id) REFERENCES user(id),
  FOREIGN KEY (friend_user_id) REFERENCES user(id)
);

-- 在friend表上创建自我外键
ALTER TABLE friend ADD CONSTRAINT fk_friend_self FOREIGN KEY (user_id) REFERENCES friend (friend_user_id);

MySQL自我外键的语法

在MySQL中,创建自我外键的语法与创建外键的方式是类似的,只需要将外键的参考列设为自己的列即可。

ALTER TABLE 表名 ADD CONSTRAINT 外键名称 
FOREIGN KEY (参考列) REFERENCES 表名(自己的列);

MySQL自我外键的限制

  1. 只适用于InnoDB存储引擎

自我外键约束只适用于InnoDB存储引擎,因为它是InnoDB存储引擎的特性之一。如果使用MyISAM存储引擎,将无法使用自我外键约束。

  1. 自我外键与主键

自我外键不容许涉及主键列,否则此自我外键将无效。原因是主键列一定有一个唯一索引,而此唯一索引会与外键约束产生矛盾。

  1. 外键删除操作

删除表中某一行时,如果该行被其他行所引用,MySQL将不会自动地删除该行,而是会引发一个错误。因此,删除表中的行时,需要事先删除与之相关的自我外键约束。

MySQL自我外键的修改和删除

  1. 修改自我外键

在MySQL中,如果需要修改自我外键,可以先使用DROP CONSTRAINT语句删除原有的自我外键,再使用ADD CONSTRAINT语句添加修改后的自我外键。

ALTER TABLE table_name DROP CONSTRAINT foreign_key_name;
ALTER TABLE table_name ADD CONSTRAINT new_foreign_key_name FOREIGN KEY (column_name) REFERENCES table_name (self_column_name);
  1. 删除自我外键

在MySQL中,可以使用DROP CONSTRAINT语句删除自我外键约束。

ALTER TABLE table_name DROP CONSTRAINT foreign_key_name;

案例分析

本案例将介绍如何使用自我外键来创建一张简单的部门表,以实现部门管理。该表结构如下:

CREATE TABLE department(
  id INT PRIMARY KEY,
  name VARCHAR(255),
  parent_id INT,
  CONSTRAINT fk_department_self FOREIGN KEY (parent_id) REFERENCES department (id)
);

在该表结构中,id列为主键,parent_id列为自我外键,用于建立部门之间的父子级关系。

我们可以在该表中插入以下数据:

INSERT INTO department (id, name, parent_id) VALUES
(1, '总公司', NULL),
(2, '销售部', 1),
(3, '财务部', 1),
(4, '研发部', 1),
(5, '市场部', 4),
(6, '前端开发组', 5),
(7, '后端开发组', 5);

以上数据将会形成一颗以”总公司”为根节点的树形结构,如下所示:

总公司
├── 销售部
├── 财务部
└── 研发部
    ├── 市场部
    │   ├── 前端开发组
    │   └── 后端开发组

我们可以使用如下SQL查询语句来获取整张部门表的树形结构:

WITH RECURSIVE cte(id, name, parent_id, lvl) AS (
  SELECT id, name, parent_id, 0 FROM department WHERE parent_id IS NULL
  UNION ALL
  SELECT department.id, department.name, department.parent_id, lvl + 1 FROM department
  JOIN cte ON department.parent_id = cte.id
)
SELECT id, CONCAT(REPEAT('-', lvl * 2), name) AS name FROM cte
ORDER BY id;

该查询语句将会返回以下结果:

id | name
---|------------------
1  | 总公司
2  | -- 销售部
3  | -- 财务部
4  | -- 研发部
5  | ---- 市场部
6  | ------ 前端开发组
7  | ------ 后端开发组

总结

在MySQL中,使用自我外键可以方便地建立表中行之间的父子级关系,并可以轻松形成树形结构。此外,自我外键还能够限制表中的数据引用过程中的错误,从而更好地保证表的数据完整性。虽然使用自我外键有一定的限制,但对于父子级表结构和朋友关系表结构等场景来说,很多情况下MySQL自我外键都是非常有用的一种约束方式。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程