一、主键和外键的作用
定义主键和外键主要是为了维护关系数据库的完整性,总结一下:
主键是能确定一条记录的唯一标识,比如,一条记录包括身份正号,姓名,年龄。身份证号是唯一能确定你这个人的,其他都可能有重复,所以,身份证号是主键。
外键用于与另一张表的关联。是能确定另一张表记录的字段,用于保持数据的一致性。比如,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);ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`learndb2`.`user1`, CONSTRAINT `user1_ibfk_1` FOREIGN KEY (`pId`) REFERENCES `provinces` (`id`))
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)