MySQL 中外键与使用详解
外键字段必须先是一个索引,否则将会先创建索引,然后才能创建外键。
如果外键字段为混合键值其中一个,需要为该字段建立单独索引。删除的时候必须先删除外键,才能删除索引。
子表中外键字段数据要么为null,要么为父表中引用字段数据!
【1】创建表的时候增加外键
此时创建的索引使用默认名字;创建的外键为表默认名字。
create table my_foreign1(
id int PRIMARY KEY auto_increment,
name varchar(20) default null COMMENT '名字',
age int,
p_id INT,
FOREIGN KEY (p_id) REFERENCES p_user_2(id)
)CHARSET utf8;-- FOREIGN KEY fk_id(p_id) REFERENCES p_user_2(id)
--将指定索引名字为fk_id,但是不能改变外键名字。
查看表结构
CREATE TABLE `my_foreign1` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(20) DEFAULT NULL COMMENT '名字',`age` int(11) DEFAULT NULL,`p_id` int(11) DEFAULT NULL,PRIMARY KEY (`id`),KEY `p_id` (`p_id`),// 先添加了索引,再创建外键CONSTRAINT `my_foreign1_ibfk_1` FOREIGN KEY (`p_id`) REFERENCES `p_user_2` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
创建表时创建外键并指定索引名字和外键名字
create table my_foreign1(
id int PRIMARY KEY auto_increment,
name varchar(20) default null COMMENT '名字',
age int,
p_id INT,
CONSTRAINT fk_pid FOREIGN KEY (p_id) REFERENCES p_user_2(id)
)CHARSET utf8;-- 索引和外键名字都为 fk_pid;
查看表结构
CREATE TABLE `my_foreign1` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(20) DEFAULT NULL COMMENT '名字',`age` int(11) DEFAULT NULL,`p_id` int(11) DEFAULT NULL,PRIMARY KEY (`id`),KEY `fk_pid` (`p_id`),CONSTRAINT `fk_pid` FOREIGN KEY (`p_id`) REFERENCES `p_user_2` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
【2】创建表后为表增加外键
语法格式如下:
alter table [table_name]
add [constraint] [constraint_name]
[unique| primary key|foreign key]
([column_name])
如果外键字段没有索引,会先添加索引,然后创建外键;
ALTER TABLE t_class
add CONSTRAINT fk_teacher_id
FOREIGN KEY (t_id) REFERENCES t_teacher(t_id)
【3】为表删除外键
先删除外键,后删除索引;不能先删除索引,因为有外键约束。
ALTER TABLE t_class
drop FOREIGN KEY fk_teacher_id(外键名,非字段名);-- 根据外键名删除外键ALTER TABLE t_class
drop index fk_teacher_id;
-- 删除对应索引
【4】创建外键的几个条件
总结如下:
父表和子表引擎一致,否则报错;
保证表的存储引擎为InnoDB,否则虽然不报错但是无约束(只有index);
实际上,如果两个表都是MyISAM 引擎的,错误根本不会发生,但也不会产生外键。
两个字段数据类型一致,数据显示长度可以不同,另外需注意有符号无符号,必须一致;
两个字段都添加了独立索引,如果子表外键字段无索引,那么在创建外键的时候会自动先添加索引;如果父表字段无索引,将报错;
字段是否允许为空,在更新或删除时候对外键字段操作有关;如外键创建时候 on delete set null on udpate cascade。但是子表外键字段不允许为空, 矛盾,创建不成功。
字段的字符集和校对集(外键类型为字符的时候);
外键名字不能重复,是针对数据库而不是表;
子表外键字段 - 数据 为父表引用字段子集;
字段可能为混合键值中一个,没有自己独立索引。外键字段必须有自己独立索引。
【5】外键的作用
外键默认的作用有两点:一个对父表,一个对子表(外键字段所在的表)。
对子表约束
子表数据在进行写操作(增和改)的时候,如果对应的外键字段在父表找不到对应的匹配,那么操作会失败。插入的时候外键字段值要么为null,要么为父表中字段。
INSERT into my_foreign1 values(null,'嘉嘉',12,40)
插入的40为外键字段数据,在父表中对应的被引用字段无此数据值。
对父表约束
父表数据进行写操作(删和改:都必须涉及到字段本身),如果对应的字段在子表中已经被数据所引用,那么就不允许操作。
INSERT into my_foreign1 values(null,'皇甫',18,2)
INSERT into my_foreign1 values(null,'嘉嘉',12,4)
2,4分别为父表里面被引用的字段数据。现在尝试更改2:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0o3QaJtp-1654482724968)(https://img-blog.csdn.net/20170606170723575?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvSjA4MDYyNA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)]
【6】外键约束模式
外键约束有三种约束模式:都是针对父表; 对应MySQL有四种约束:RESTRICT,NO ACTION , CASCADE , SET NULL。
① RESTRICT
严格模式(默认的),父表不能删除或者更新一个已经被子表引用的记录数据(外键对应的父表被引用的字段,其他字段可以更改)。
即,当父表字段数据已经被子表引用时,不能再删除或者更新父表被引用的字段数据。
示例如下:
ALTER TABLE my_foreign1 add CONSTRAINT fk_id
FOREIGN KEY (p_id) REFERENCES p_user_2(id)
ON DELETE NO ACTION ON UPDATE NO ACTION;-- 或者
ON DELETE RESTRICT ON UPDATE RESTRICT;
② Cascade
级联模式;针对父表的操作,对应子表关联的数据也跟着被操作。
- 更新父表被引用的字段,如果该数据被子表外键使用,则子表外键随之更新;
- 删除父表被引用的字段记录,如果该数据被子表外键使用,子表对应外键所属记录随之删除。
示例如下:
ALTER TABLE my_foreign1 add CONSTRAINT fk_id
FOREIGN KEY (p_id) REFERENCES p_user_2(id)
ON DELETE CASCADE ON UPDATE CASCADE;
③Set null
置空模式,父表字段操作之后,如果该数据被子表外键使用,子表对应的外键字段被置空。
外键置空的前提是对应字段允许为空,否则外键创建不成功。
示例如下:
ALTER TABLE my_foreign1 add CONSTRAINT fk_id
FOREIGN KEY (p_id) REFERENCES p_user_2(id)
ON DELETE SET NULL ON UPDATE SET NULL;
通常一个合理的做法(约束模式)是:删除的时候子表置空,更新的时候子表级联:
ON DELETE SET NULL ON UPDATE CASCADE;
【7】创建外键出现的错误
① errno: 150错误:
这种情况下,参考创建外键的几个条件,一一排查。
② error:121错误:
这种情况下显然是你的外键名字重复。MySQL判断外键名字基础单位是数据库,而不是表。
用如下语句查看数据库已经存在的外键与所属表:
SELECTconstraint_name,table_name
FROMinformation_schema.table_constraints
WHEREconstraint_type = 'FOREIGN KEY'
AND table_schema = DATABASE()
ORDER BYconstraint_name;
MySQL 中外键与使用详解相关推荐
- mysql临键锁_详解 MySql InnoDB 中的三种行锁(记录锁、间隙锁与临键锁)
详解 MySql InnoDB 中的三种行锁(记录锁.间隙锁与临键锁) 前言 InnoDB 通过 MVCC 和 NEXT-KEY Locks,解决了在可重复读的事务隔离级别下出现幻读的问题.MVCC ...
- mysql 主键溢出检查_详解MySQL 表中非主键列溢出情况监控
今天,又掉坑了. 之前踩到过MySQL主键溢出的情况,通过prometheus监控起来了. 这次遇到的坑,更加的隐蔽. 是一个log表里面的一个int signed类型的列写满了.快速的解决方法当然还 ...
- mysql 外键设置_详解MySQL外键设置
MySQL外键设置是学习MySQL数据库过程中不能不提的,下面就会为您详细介绍MySQL外键设置的方法,希望对您学习MySQL外键设置方面能有所帮助. 外键的作用: 保持数据一致性,完整性,主要目的是 ...
- mysql入门优化_MySQL数据库:MySQL十大优化技巧详解
本文主要向大家介绍了MySQL数据库的MySQL十大优化技巧详解,通过具体的内容向大家展现,希望对大家学习MySQL数据库有所帮助. WEB开发者不光要解决程序的效率问题,对数据库的快速访问和相应也是 ...
- mysql 聚集函数 count 使用详解
mysql 聚集函数 count 使用详解 本文将探讨以下问题 1.count(*) . count(n).count(null)与count(fieldName) 2.distinct 与 coun ...
- MySQL数据类型以及基本使用详解
MySQL数据类型以及基本使用详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.MySQL服务器的主要组件 我们知道MySQL的主要组件主要是由服务端(mysqld)和客户端 ...
- linux 用root安装mysql数据库_Linux上安装Mysql及简单的使用详解
1. 安装mysql sudo apt-get update sudo apt-get install mysql-server sudo apt-get install python-mysqldb ...
- docker导入MySQL文件_Docker容器中Mysql数据的导入/导出详解
前言 Mysql数据的导入导出我们都知道一个mysqldump命令就能够解决,但如果是运行在docker环境下的mysql呢? 解决办法其实还是用mysqldump命令,但是我们需要进入docker的 ...
- php mysql无限_php+mysql实现无限分类实例详解
php+mysql实现无限分类实例详解 fenlei($arr[$i][0]); //$arr[$i][1]表示第$i+1个分类的id的值.进行递归,也就是把自己的id作为f_id参数把自己的子类 ...
最新文章
- 做一个有姿态的女孩子
- 韩军星:汇报工作的四个层级
- 电子表单设计,表单打印,表单填写,数据发布,VC++,VB,源代码组件库
- 画图软件怎么做性能测试,软件性能测试能力提升解决方案.pdf
- 什么是3G-SDI光端机?
- nginx模块nginx_upstream_check_module来检查后端服务器的健康情况
- 启动root用户 银河麒麟_银河麒麟桌面版系统-用户密码到期无法正常进入系统解决办法...
- 微型计算机原理与接口技术知识点
- Matlab绘制简单动画
- 商超霸主之争:天猫节节败退 沦为京东陪练
- 计算机管理员权限打不开怎么办,administrator管理员权限怎么打开?
- 量子通信,究竟是怎样保障信息安全的?
- 硬件开发:嵌入式系统知识和接口技术(值得收藏)
- 基因组序列genbank格式和fasta格式批量下载
- Android开发 报错: xxx does not have a NavController set on xxx
- 一段从API读取基金净值信息并写入Excel表的Python代码
- 数字孪生技术打造智慧车联网数据可视化大屏
- 有10瓶药 里面有9瓶是无毒的 有1瓶毒药
- 7月29日绝地求生服务器维护,绝地求生7月29日正式服维护公告内容一览
- 文件查找 find locate