【linux】循序渐进学运维-MySQL-外键约束

外键约束
什么是外键约束
MySQL的外键约束是用来在两个表之间建立链接的,其中一个表发生变化,另外一个表也发生变化。从这个特点来看,它主要是为了保证表数据的一致性和完整性的。

对于两个通过外键关联的表,相关联字段中主键所在的表是主表,也称之为父表,外键所在的表是从表,也称之为子表,定义外键的时候需要遵守几个规则:

1、父表必须已经存在于数据库中,或者是当前正在创建的表。如果是后一种情况,则父表与子表是同一个表,这样的表称为自参照表,这种结构称为自参照。
2、必须为父表定义主键。
3、主键不能包含空值,但允许在外键中出现空值。也就是说,只要外键的每个非空值出现在指定的主键中,这个外键的内容就是正确的。
4、外键中列的数目必须和父表的主键中列的数目相同。

举例:
有二张表,一张是用户表,一张是订单表
如果两张表没有关联,会出现两种情况:

  1. 如果我删除了用户表里的用户,那么订单表里面与这个用户有关的数据,就成了无头数据了,不完整了。
  2. 如果我在订单表里面,随便插入了一条数据,这个订单在用户表里面,没有与之对应的用户。这样数据也不完整了。
    所以我们要引入外键这个概念
    上面的两张表有外键的话,就方便多了,可以不让用户删除数据,或者删除用户的话,通过外键同样删除订单表里面的数据,这样也能让数据完整。

外键约束的语法:

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

方法一:通过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  外部表名  (关联的字段)  ENGINE =innodb 

注:创建成功,必须满足以下4个条件:

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

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

mysql> create table `user`(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;
Query OK, 0 rows affected (0.02 sec)

需要注意的是:创建时,如果表名是sql关键字,使用时,需要使用反引号``
创建订单表

mysql> create table `order1`(order_id int(11) auto_increment, u_id int(11) default '0', username varchar(40),money int(11),primary key(order_id),index(u_id),foreign key order_f_key(u_id) references user(id) on delete cascade on update cascade) type=innodb;

Query OK, 0 rows affected (0.00 sec)

注:
on delete cascade on update cascade 添加级联删除和更新。
确保参照的表user中id字段存在。 组成外键的字段u_id被索引。 必须使用type指定存储引擎为:innodb。

外键字段和关联字段,数据类型必须一致。
插入测试数据

mysql> insert into `user`(name,sex)values('zr',2),('wld',1),('zmedu',1);
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0
mysql> insert into `order1`(u_id,username,money)values(1,'zr',10000),(1,'wld',13000),(3,'ljc',25000);
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0
mysql> select * from `order1`;
+------+------+----------+-------+
| o_id | u_id | username | money |
+------+------+----------+-------+
|    1 |    1 | zr       | 10000 |
|    2 |    1 | wld      | 13000 |
|    3 |    3 | ljc      | 25000 |
+------+------+----------+-------+
3 rows in set (0.00 sec)

mysql> select * from `user`;
+----+-------+-----+
| id | name  | sex |
+----+-------+-----+
|  1 | zr    |   2 |
|  2 | wld   |   1 |
|  3 | zmedu |   1 |
+----+-------+-----+
3 rows in set (0.00 sec)


mysql> select id,name,sex,money, o_id from `user`,`order1` where id=u_id;
+----+-------+-----+-------+------+
| id | name  | sex | money | o_id |
+----+-------+-----+-------+------+
|  1 | zr    |   2 | 10000 |    1 |
|  1 | zr    |   2 | 13000 |    2 |
|  3 | zmedu |   1 | 25000 |    3 |
+----+-------+-----+-------+------+
3 rows in set (0.00 sec)

测试级联删除:
我们删除用户id1, 查看order1中id为1用户是否被删除

mysql> delete from user where id =1;
Query OK, 1 row affected (0.00 sec)

mysql> select * from `order1`;
+----------+------+----------+-------+
| order_id | u_id | username | money |
+----------+------+----------+-------+
|        3 |    3 | ljc      | 25000 |
+----------+------+----------+-------+
1 row in set (0.00 sec)

测试级联更新:
更新前数据状态


mysql> select * from `order1`;
+----------+------+----------+-------+
| order_id | u_id | username | money |
+----------+------+----------+-------+
|        3 |    3 | ljc      | 25000 |
+----------+------+----------+-------+
1 row in set (0.00 sec)

mysql> select * from user;
+----+-------+-----+
| id | name  | sex |
+----+-------+-----+
|  2 | wld   |   1 |
|  3 | zmedu |   1 |
+----+-------+-----+
2 rows in set (0.00 sec)

mysql> update user set id=5 where id=3;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from user;
+----+-------+-----+
| id | name  | sex |
+----+-------+-----+
|  2 | wld   |   1 |
|  5 | zmedu |   1 |
+----+-------+-----+
2 rows in set (0.00 sec)

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

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

14.4.3 删除外键
语法
alter table 数据表名称 drop foreign key 约束(外键)名称
mysql> alter table order1 drop foreign key order1_ibfk_1;
mysql> show create table order1;

初始order1,查看

show create table order1;
+--------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table  | Create Table                                                                                                                                                                                                                                                                                                                                                                                       |
+--------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

| order1 | CREATE TABLE `order1` (
  `order_id` int(11) NOT NULL AUTO_INCREMENT,
  `u_id` int(11) DEFAULT '0',
  `username` varchar(40) DEFAULT NULL,
  `money` int(11) DEFAULT NULL,
  PRIMARY KEY (`order_id`),
  KEY `u_id` (`u_id`),
  CONSTRAINT `order1_ibfk_1` FOREIGN KEY (`u_id`) REFERENCES `user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 |
+--------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> alter table order1 drop foreign key order1_ibfk_1;
Query OK, 1 row affected (0.02 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> show create table order1;
+--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table  | Create Table                                                                                                                                                                                                                                                                       |
+--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| order1 | CREATE TABLE `order1` (
  `order_id` int(11) NOT NULL AUTO_INCREMENT,
  `u_id` int(11) DEFAULT '0',
  `username` varchar(40) DEFAULT NULL,
  `money` int(11) DEFAULT NULL,
  PRIMARY KEY (`order_id`),
  KEY `u_id` (`u_id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 |

1 row in set (0.00 sec)



发布了256 篇原创文章 · 获赞 56 · 访问量 11万+

猜你喜欢

转载自blog.csdn.net/xinshuzhan/article/details/102850437