1.什么是外键约束

外键约束(foreign key)就是表与表之间的某种约定的关系,由于这种关系的存在,我们能够让表与表之间的数据,更加的完整,关连性更强。

关于数据表的完整性和关连性,可以举个例子

有二张表,一张是用户表,一张是订单表:

1.如果我删除了用户表里的用户,那么订单表里面跟这个用户有关的数据,就成了无头数据了,不完整了。
2.如果我在订单表里面,随便插入了一条数据,这个订单在用户表里面,没有与之对应的用户。这样数据也不完整了。

如果有外键的话,就方便多了,可以不让用户删除数据,或者删除用户的话,通过外键同样删除订单表里面的数据,这样也能让数据完整。

通过外键约束,每次插入或更新数据表时,都会检查数据的完整性。

2.创建外键约束

2.1 方法一:通过create table创建外键

语法:

create table 数据表名称(
...,
[CONSTRAINT [约束名称]] FOREIGN KEY [外键字段]
    REFERENCES [外键表名](外键字段,外键字段2…..)
    [ON DELETE CASCADE ]
    [ON UPDATE CASCADE ]
)

参数的解释:

RESTRICT: 拒绝对父表的删除或更新操作。
CASCADE: 从父表删除或更新且自动删除或更新子表中匹配的行。ON DELETE CASCADE和ON UPDATE CASCADE都可用

注意:on update cascade是级联更新的意思,on delete cascade是级联删除的意思,意思就是说当你更新或删除主键表,那外键表也会跟随一起更新或删除。

精简化后的语法:

foreign key 当前表的字段 references 外部表名 (关联的字段) type=innodb

2.1.1 插入测试数据

例子:我们创建一个数据库,包含用户信息表和订单表

MariaDB [book]> create database market;				# 创建market数据库
Query OK, 1 row affected (0.00 sec) MariaDB [book]> use market; # 使用market数据库
Database changed MariaDB [market]> create table userprofile(id int(11) not null auto_increment, name varchar(50) not null default '', sex int(1) not null default '0', primary key(id))ENGINE=innodb; # 创建userprofile数据表,指定使用innodb引擎
Query OK, 0 rows affected (0.07 sec) MariaDB [market]> create table user_order(o_id int(11) auto_increment, u_id int(11) default '0', username varchar(50), money int(11), primary key(o_id), index(u_id), foreign key order_f_key(u_id) references userprofile(id) on delete cascade on update cascade); # 创建user_order数据表,同时为user_order表的u_id字段做外键约束,绑定userprofile表的id字段
Query OK, 0 rows affected (0.04 sec) MariaDB [market]> insert into userprofile(name,sex)values('HA',1),('LB',2),('HPC',1); # 向userprofile数据表插入三条记录
Query OK, 3 rows affected (0.01 sec)
Records: 3 Duplicates: 0 Warnings: 0 MariaDB [market]> select * from userprofile; # 查询userprofile数据表的所有记录
+----+------+-----+
| id | name | sex |
+----+------+-----+
| 1 | HA | 1 |
| 2 | LB | 2 |
| 3 | HPC | 1 |
+----+------+-----+
3 rows in set (0.00 sec) MariaDB [market]> insert into user_order(u_id,username,money)values(1,'HA',234),(2,'LB',146),(3,'HPC',256); # 向user_order数据表插入三条记录
Query OK, 3 rows affected (0.02 sec)
Records: 3 Duplicates: 0 Warnings: 0 MariaDB [market]> select * from user_order; # 查询user_order数据表的所有记录
+------+------+----------+-------+
| o_id | u_id | username | money |
+------+------+----------+-------+
| 1 | 1 | HA | 234 |
| 2 | 2 | LB | 146 |
| 3 | 3 | HPC | 256 |
+------+------+----------+-------+
3 rows in set (0.00 sec) MariaDB [market]> select id,name,sex,money,o_id from userprofile,user_order where id=u_id; # 联表查询
+----+------+-----+-------+------+
| id | name | sex | money | o_id |
+----+------+-----+-------+------+
| 1 | HA | 1 | 234 | 1 |
| 2 | LB | 2 | 146 | 2 |
| 3 | HPC | 1 | 256 | 3 |
+----+------+-----+-------+------+
3 rows in set (0.03 sec)

2.1.2 测试级联删除

MariaDB [market]> delete from userprofile where id=1;		# 删除user表中id为1的数据
Query OK, 1 row affected (0.01 sec) MariaDB [market]> select id,name,sex,money,o_id from userprofile,user_order where id=u_id;
+----+------+-----+-------+------+
| id | name | sex | money | o_id |
+----+------+-----+-------+------+
| 2 | LB | 2 | 146 | 2 |
| 3 | HPC | 1 | 256 | 3 |
+----+------+-----+-------+------+
2 rows in set (0.00 sec) MariaDB [market]> select * from user_order; # 查看order表的数据
+------+------+----------+-------+
| o_id | u_id | username | money |
+------+------+----------+-------+
| 2 | 2 | LB | 146 |
| 3 | 3 | HPC | 256 |
+------+------+----------+-------+
3 rows in set (0.00 sec)

2.1.3 测试级联更新

更新数据之前的状态

MariaDB [market]> select * from userprofile;				# 查看userprofile表的数据
+----+------+-----+
| id | name | sex |
+----+------+-----+
| 2 | LB | 2 |
| 3 | HPC | 1 |
+----+------+-----+
3 rows in set (0.00 sec) MariaDB [market]> select * from user_order; # 查看order表的数据
+------+------+----------+-------+
| o_id | u_id | username | money |
+------+------+----------+-------+
| 2 | 2 | LB | 146 |
| 3 | 3 | HPC | 256 |
+------+------+----------+-------+
3 rows in set (0.00 sec)

更新数据

MariaDB [market]> update userprofile set id=6 where id=2;	# 把userprofile数据表中id为2的用户改为id为6
Query OK, 1 row affected (0.02 sec)
Rows matched: 1 Changed: 1 Warnings: 0

更新数据后的状态

MariaDB [market]> select id,name,sex,money,o_id from userprofile,user_order where id=u_id;		# 联表查询,可以看出表中已经没有id为2的用户了
+----+------+-----+-------+------+
| id | name | sex | money | o_id |
+----+------+-----+-------+------+
| 6 | LB | 2 | 146 | 2 |
| 3 | HPC | 1 | 256 | 3 |
+----+------+-----+-------+------+
2 rows in set (0.00 sec) MariaDB [market]> select * from userprofile; # 查看userprofile表的数据,id只剩下3和6
+----+------+-----+
| id | name | sex |
+----+------+-----+
| 3 | HPC | 1 |
| 6 | LB | 2 |
+----+------+-----+
2 rows in set (0.00 sec) MariaDB [market]> select * from user_order; # 查看user_order表的数据,u_id也改为6
+------+------+----------+-------+
| o_id | u_id | username | money |
+------+------+----------+-------+
| 2 | 6 | LB | 146 |
| 3 | 3 | HPC | 256 |
+------+------+----------+-------+
2 rows in set (0.00 sec)

2.1.4 测试数据完整性

MariaDB [market]> insert into user_order(u_id,username,money)values(5,"XJ",345);		# 单独向user_order数据表中插入数据,插入数据失败
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`market`.`user_order`, CONSTRAINT `user_order_ibfk_1` FOREIGN KEY (`u_id`) REFERENCES `userprofile` (`id`) ON DELETE CASCADE ON UPDATE CASCADE)

在上面的例子中,user_order表的外键约束,user_order表受userprofile表的约束

user_order里面插入一条数据u_id为5用户,在userprofile表里面根本没有,所以插入数据失败

先向userprofile表中插入记录,再向user_order表中插入记录就可以了

MariaDB [market]> insert into userprofile values(5,"XJ",1);			# 先向userprofile数据表中插入id为5的记录,插入数据成功
Query OK, 1 row affected (0.01 sec) MariaDB [market]> insert into user_order(u_id,username,money) values(5,"XJ",345); # 再向user_order数据表中插入数据,成功
Query OK, 1 row affected (0.00 sec) MariaDB [market]> select * from userprofile; # 查询userprofile数据表中的所有记录
+----+------+-----+
| id | name | sex |
+----+------+-----+
| 3 | HPC | 1 |
| 5 | XJ | 1 |
| 6 | LB | 2 |
+----+------+-----+
3 rows in set (0.00 sec) MariaDB [market]> select * from user_order; # 查询user_order数据表中的所有记录
+------+------+----------+-------+
| o_id | u_id | username | money |
+------+------+----------+-------+
| 2 | 6 | LB | 146 |
| 3 | 3 | HPC | 256 |
| 5 | 5 | XJ | 345 |
+------+------+----------+-------+
3 rows in set (0.01 sec)

2.2 方法二:通过alter table创建外键和级联更新,级联删除

语法:

alter table 数据表名称 add
[constraint [约束名称] ] foreign key (外键字段,..) references 数据表(参照字段,...)
[on update cascade|set null|no action]
[on delete cascade|set null|no action]
)

例子:

MariaDB [market]> create table user_order1(o_id int(11) auto_increment,u_id int(11) default "0",username varchar(50),money int(11),primary key(o_id),index(u_id));			# 创建user_order1数据表,创建表时不使用外键约束
Query OK, 0 rows affected (0.11 sec) MariaDB [market]> show create table user_order1; # 查看user_order1数据表的创建信息,没有外键约束
+-------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| user_order1 | CREATE TABLE `user_order1` (
`o_id` int(11) NOT NULL AUTO_INCREMENT,
`u_id` int(11) DEFAULT '0',
`username` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
`money` int(11) DEFAULT NULL,
PRIMARY KEY (`o_id`),
KEY `u_id` (`u_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci |
+-------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.01 sec) MariaDB [market]> alter table user_order1 add foreign key(u_id) references userprofile(id) on delete cascade on update cascade; # 使用alter修改user_order1数据表,为user_order1数据表添加外键约束
Query OK, 0 rows affected (0.05 sec)
Records: 0 Duplicates: 0 Warnings: 0 MariaDB [market]> show create table user_order1; # 查看user_order1数据表的创建信息,已经添加了外键约束
+-------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| user_order1 | CREATE TABLE `user_order1` (
`o_id` int(11) NOT NULL AUTO_INCREMENT,
`u_id` int(11) DEFAULT '0',
`username` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
`money` int(11) DEFAULT NULL,
PRIMARY KEY (`o_id`),
KEY `u_id` (`u_id`),
CONSTRAINT `user_order1_ibfk_1` FOREIGN KEY (`u_id`) REFERENCES `userprofile` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci |
+-------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

3.删除外键

语法

alter table 数据表名称 drop foreign key 约束(外键)名称

例子:

MariaDB [market]> show create table user_order1;			# 查看user_order1数据表的创建信息,包含外键约束
+-------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| user_order1 | CREATE TABLE `user_order1` (
`o_id` int(11) NOT NULL AUTO_INCREMENT,
`u_id` int(11) DEFAULT '0',
`username` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
`money` int(11) DEFAULT NULL,
PRIMARY KEY (`o_id`),
KEY `u_id` (`u_id`),
CONSTRAINT `user_order1_ibfk_1` FOREIGN KEY (`u_id`) REFERENCES `userprofile` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci |
+-------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec) MariaDB [market]> alter table user_order1 drop foreign key user_order1_ibfk_1; # 为user_order1数据表删除外键约束,外键名称必须与从`show create table user_order1`语句中查到的相同
Query OK, 0 rows affected (0.05 sec)
Records: 0 Duplicates: 0 Warnings: 0 MariaDB [market]> show create table user_order1; # 查看user_order1数据表的创建信息,外键约束已经被删除了
+-------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| user_order1 | CREATE TABLE `user_order1` (
`o_id` int(11) NOT NULL AUTO_INCREMENT,
`u_id` int(11) DEFAULT '0',
`username` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
`money` int(11) DEFAULT NULL,
PRIMARY KEY (`o_id`),
KEY `u_id` (`u_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci |
+-------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

4.使用外键约束的条件

要想外键创建成功,必须满足以下4个条件:

1、确保参照的表和字段存在。
2、组成外键的字段被索引。
3、必须使用type指定存储引擎为:innodb.
4、外键字段和关联字段,数据类型必须一致。

5.使用外键约束需要的注意事项

1.on delete cascade  on update cascade 添加级联删除和更新:
2.确保参照的表userprofile中id字段存在。
3.确保组成外键的字段u_id被索引
4.必须使用type指定存储引擎为:innodb。
5.外键字段和关联字段,数据类型必须一致。

详解MariaDB数据库的外键约束的更多相关文章

  1. [转帖]详解oracle数据库唯一主键SYS_GUID()

    详解oracle数据库唯一主键SYS_GUID() https://www.toutiao.com/i6728736163407856139/ 其实 需要注意 这里满不能截取 因为截取了 就不一定唯一 ...

  2. MySQL数据库有外键约束时使用truncate命令的办法

    MySQL数据库操作中,Delete与Truncate两个命令都可以删除一个数据表中的全部数据,使用办法分别是: DELETE FROM t_question TRUNCATE TABLE t_que ...

  3. mysql数据库导入外键约束问题

    在网站搬迁过程中,很重要一点是数据的迁移.你的数据库可能已经包含了一个设计良好的数据表集合,并且在网站运营过程中,产生了重要的数据.这时你必须做好包含数据表schema以及数据本身的迁移. 完成上述数 ...

  4. 数据库 SQL 外键约束 多表查询

    多表设计与多表查询 1.外键约束        表是用来保存现实生活中的数据的,而现实生活中数据和数据之间往往具有一定的关系,我们在使用表来存储数据时,可以明确的声明表和表之前的依赖关系,命令数据库来 ...

  5. 详解MariaDB数据库的事务

    1.什么是事务 数据库事务:(database transaction): 事务是由一组SQL语句组成的逻辑处理单元,一组事务中的SQL语句要不全部执行成功功:如果其中某一条执行失败,则这组SQL语句 ...

  6. 详解MariaDB数据库的索引

    1.什么是索引 索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含着对数据表里所有记录的引用指针. 更通俗的说,数据库索引好比是一本书前面的目录,在查找内容之前可以先在 ...

  7. 详解MariaDB数据库的触发器

    1.什么是触发器 触发器是一种特殊的存储过程,它在插入,删除或修改特定表中的数据时触发执行 它比数据库本身标准的功能有更精细和更复杂的数据控制能力 2.触发器的作用: 2.1 安全性 可以基于数据库的 ...

  8. 详解MariaDB数据库的存储过程

    1.什么是存储过程 很多时候,SQL语句都是针对一个或多个表的单条语句.但是也有时候有的查询语句需要进行多次联表查询才能完成,此时就需要用到存储过程了. 存储过程(Stored Procedure)是 ...

  9. Constraint6:更新外键约束(Foreign Key Constraint)的引用列

    在SQL Server中,表之间存在引用关系,引用关系通过创建外键约束(Foreign Key Constraint)实现.如果一个Table中的column被其他Table引用,那么该表是参考表,或 ...

随机推荐

  1. list遍历时删除的坑

    1.测试代码如下: public class StrTest { public static void main(String[] args) { ArrayList<String> li ...

  2. 通过Linq查找重复数据

    一.模拟初始化集合数据 List<Student> students = new List<Student>() { new Student(){ Age=18,Name=&q ...

  3. 一道php笔试题

    原文地址: http://www.walu.cc/php/a-bishiti.md 问题: 请找出下面代码中的问题,修复并优化. <?php //批量注册用户,每次>100个. //注册新 ...

  4. python并发编程之多进程基础知识点

    1.操作系统 位于硬件与应用软件之间,本质也是一种软件,由系统内核和系统接口组成 和进程之间的关系是: 进程只能由操作系统创建 和普通软件区别: 操作系统是真正的控制硬件 应用程序实际在调用操作系统提 ...

  5. echart在X轴下方添加字

    使用Echart做统计图表,这个方便快捷还高大上 官方网址 https://www.echartsjs.com/ 按照文档,很快就做出了一个柱图表 在X轴下方,要显示出对应日期是星期几(上图最下方,用 ...

  6. palacehoder的自定义样式【输入框input /文本域textarea】

    7.palacehoder的自定义样式[输入框input /文本域textarea] 因为每个浏览器的CSS选择器都有所差异,所以需要针对每个浏览器做单独的设定(可以在冒号前面写input和texta ...

  7. C语言博客作业06——结构体&文件

    C语言博客作业06--结构体&文件 1.本章学习总结 1.1思维导图 1.2.本章学习体会 在本周的学习中,我们学习了关于结构体和文件的内容.结构体的本身并不难,但以结构体为基础的链表还是让我 ...

  8. Unity支持的跨平台

    Windows Mac OS X Web Browsers IOS android PlayStation 3 Xbox 360 Windows Store Windows Phone Linux B ...

  9. C/C++面试题:编写类String的构造函数、析构函数和赋值函数。

    转https://www.cnblogs.com/alinh/p/9636500.html 考点:构造函数.析构函数和赋值函数的编写方法出现频率:☆☆☆☆☆已知类String的原型为:         ...

  10. JSON使用与类型转换

    JSON语法与对象 JSON方法与使用 一.JSON语法与对象 JSON是英文JavaScript Object Notation(JavaScript 对象表示法)的缩写,是存储和交换文本信息的语法 ...