一、主键和外键的作用
定义主键和外键主要是为了维护关系数据库的完整性,总结一下:
主键是能确定一条记录的唯一标识,比如,一条记录包括身份正号,姓名,年龄。身份证号是唯一能确定你这个人的,其他都可能有重复,所以,身份证号是主键。
外键用于与另一张表的关联。是能确定另一张表记录的字段,用于保持数据的一致性。比如,A表中的一个字段,是B表的主键,那他就可以是A表的外键。
二、主键、外键和索引的区别
定义:
- 主键--唯一标识一条记录,不能有重复的,不允许为空
- 外键--表的外键是另一表的主键, 外键可以有重复的, 可以是空值
- 索引--该字段没有重复值,但可以有一个空值
作用:
- 主键--用来保证数据完整性
- 外键--用来和其他表建立联系用的
- 索引--是提高查询排序的速度
个数:
- 主键--主键只能有一个
- 外键--一个表可以有多个外键
- 索引--一个表可以有多个唯一索引
三、创建外键的形式
1、创建表时添加
[CONSTARINT 外键名称(一般格式:当前表_fk_主表)] FOREIGN KEY(外键列) PEFERENCES 主表(字段)
-- 将user1表的pId与省份表的id字段关联
mysql> CREATE TABLE IF NOT EXISTS user1(
-> id Int UNSIGNED AUTO_INCREMENT KEY,
-> username VARCHAR(20) NOT NULL,
-> pId TINYINT UNSIGNED,
-> FOREIGN KEY(pId) REFERENCES provinces(id)
-> );
-- 将user2表的pId与省份表的id字段关联,并起别名
mysql> CREATE TABLE IF NOT EXISTS user2(
-> id Int UNSIGNED AUTO_INCREMENT KEY,
-> username VARCHAR(20) NOT NULL,
-> pId TINYINT UNSIGNED,
-> CONSTRAINT user2_fk_provinces FOREIGN KEY(pId) REFERENCES provinces(id)
-> );
mysql> SHOW CREATE TABLE user2;
| user2 | CREATE TABLE `user2` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(20) NOT NULL,
`pId` tinyint(3) unsigned DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `user2_fk_provinces` (`pId`), -- 自动添加索引
CONSTRAINT `user2_fk_provinces` FOREIGN KEY (`pId`) REFERENCES `provinces` (`id`) --添加外键
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
--外键存在的情况下插入数据
mysql> INSERT user1(username,pId) VALUES('HAHA1',1);
mysql> INSERT user1(username,pId) VALUES('HAHA1',4);
--当外键里没有对应记录时提出错误
mysql> INSERT user1(username,pId) VALUES('HAHA1',6);
a foreign key
2、表创建后通过ALTER语句添加
ALTER TABLE tbl_name ADD CONSTRAINT 约束名称 FOREIGN KEY(字段) REFERENCES 主表(字段名称)
-- 添加外键
mysql> ALTER TABLE user2 ADD CONSTRAINT user2_fk_provinces FOREIGN KEY(pId) REFERENCES provinces(id);
mysql> SHOW CREATE TABLE user2;
| user2 | CREATE TABLE `user2` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(20) NOT NULL,
`pId` tinyint(3) unsigned DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `user2_fk_provinces` (`pId`),
CONSTRAINT `user2_fk_provinces` FOREIGN KEY (`pId`) REFERENCES `provinces` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
3、删除外键
ALTER TABLE tbl_name DROP FOREIGN KEY 约束名称;
-- 删除外键
mysql> ALTER TABLE user2 DROP FOREIGN KEY user2_fk_provinces;
mysql> SHOW CREATE TABLE user2;
| user2 | CREATE TABLE `user2` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(20) NOT NULL,
`pId` tinyint(3) unsigned DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `user2_fk_provinces` (`pId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
四、创建外键需要注意的情况
1、父表和子表必须使用相同的存储引擎;禁止使用临时表
2、存储引擎只能使用INNODB
3、字表外键必须关联父表主键
4、外键列和参照列应具有相似的数据类型
5、外键列和参照列必须创建索引
五、操作父表时,子表操作规则
1、CASCADE :当父表update或者delete时,让子表级联操作
2、SET NULL:当父表update或者delete时,设置子表外键列为NULL,前提是此列没有NOT NULL约束
3、RESTRICT:拒绝对父表更新操作
4、NO ACTION:同RESTRICT
ON UPDATE|ON DELETE CASCADE|SET NULL|RESTRICT|NO ACTION
-- 建立级联操作
mysql> ALTER TABLE user1 ADD CONSTRAINT user1_fk_provinces FOREIGN KEY(pId) REFERENCES provinces(id) ON DELETE CASCADE ON UPDATE CASCADE;
-- 地址表插入一条数据
mysql> INSERT provinces(pName) VALUES('广州');
-- 向用户表插入一条数据
mysql> INSERT user1(username,pId) VALUES('HAHA1',6);
mysql> select * from provinces;
+----+-------+
| id | pName |
+----+-------+
| 4 | 上海 |
| 3 | 北京 |
| 1 | 山东 |
| 6 | 广州 |
| 2 | 河北 |
| 5 | 美国 |
+----+-------+
mysql> SELECT * FROM user1;
+----+----------+------+
| id | username | pId |
+----+----------+------+
| 1 | HAHA1 | 1 |
| 2 | HAHA1 | 4 |
| 4 | HAHA1 | 6 |
+----+----------+------+
3 rows in set (0.00 sec)
-- 当删除父表的一个条记录时
mysql> DELETE FROM provinces WHERE id=6;
Query OK, 1 row affected (0.06 sec)
-- 父表记录已经删除
mysql> select * from provinces;
+----+-------+
| id | pName |
+----+-------+
| 4 | 上海 |
| 3 | 北京 |
| 1 | 山东 |
| 2 | 河北 |
| 5 | 美国 |
+----+-------+
5 rows in set (0.00 sec)
-- 子表记录级联删除
mysql> SELECT * FROM user1;
+----+----------+------+
| id | username | pId |
+----+----------+------+
| 1 | HAHA1 | 1 |
| 2 | HAHA1 | 4 |
+----+----------+------+
2 rows in set (0.00 sec)