目录
总结
本文主要使用Navicat for MySQL工具 通过编程和代码测试 来分析SQL语言的常用约束条件:主键约束 和 外键约束。
在业务中每张表都需要有且仅有一个主键。
一张表中可以有多个外键,但是添加外键约束之后,字段添加外键约束的表作为子表,子表的外键引用来自父表的主键字段或唯一性约束的字段,被引用的表作为父表,父子表之间又有了需要注意的细节。
本文深入浅出,通过代码测试结合概念分析力求帮助读者彻底弄懂主键和外键。
1.建立时先建父表再建子表
先建立要引用的主表(外键来自何表)
再建立子表,按顺序执行,不然要报错
- 🔲正确建表语句:
drop table if exists stu;
drop table if exists class;
create table stu
(
sno int PRIMARY key,
sname VARCHAR(10),
major VARCHAR(10),
cno int foreign key references class(cno)
);
create table class
(
cno int primary,
cname VARCHAR(5)
);
2.删除时先删子表再删父表
DROP TABLE IF EXISTS class;
DROP table if exists stu;
CREATE TABLE class
(
cno int primary key,
cname VARCHAR(10)
);
create table stu
(
sno int primary key,
sname VARCHAR(5),
cno int,
FOREIGN key(cno) REFERENCES class(cno)
);
不然会报错:
正确删除方式:
3.主键:非空且唯一
主键一个表中只能有一个,可以有表级约束,也可以有列级约束。
主键就是非空约束(not null) 和 唯一性约束(unique)两者的结合
表级约束就是两个或者多个字段连起来 满足 上述要求!
主键的定义语句
sno int primary key;//列级约束,对学号这一字段(列,columu)进行约束,要求不为空且不能重复!
primary key(sno);//一个字段也可以这样使用表级约束,但是意义不大
primary key(name,id);//姓名和身份证号连起来,作为主键
尽管支持多个字段联合起来作为联合主键。
但是顺嘴提一句,并不推荐这样,实际业务中
第一范式就要求非主键不能对主键存在部分依赖。复合主键完美破解第一范式!
主键常用两种:
1,业务主键 业务主键是和业务挂钩的,数据重用效率低,业务发生变更太复杂,和业务有关,
2,自然主键 推荐使用自然主键,自然主键是和业务无关,自己玩自己的,业务变更不影响对数据的使用
其中自然主键非常常用,且提到自然主键,不得不提到主键值自增,
如:在我们插入数据时,可以不管(自然主键),插入一条数据,主键值自动增长。
insert into class
(cname)
VALUES
('jd'),('jz'),('gk');
select * from class;
insert into stu
(sname,cno)
VALUES
('cwq',1),('ljb',2),('cyc',3);
select * from stu;
执行上述语句结果如下:
原因是我们在定义主键值的时候加入了这样一句话:
cno int primary key auto_increment;
auto_increment,主键值自增
4.外键:关联其他表的主键或唯一值
外键的约束条件
首先,外键是本表中的字段,本表是子表,通常外键引用父表的主键
但是当外键引用的是父表不为主键的字段
此时外键所约束的列,可以有一个或多个null同时出现 因为null不是值,不存在重复。
即可以不满足非空约束,但要求仍然满足unique的唯一性约束,不能有重复
外键:一言以蔽之:关联其他表的主键或唯一值
外键的声明语法:
foreign key(字段名) references 主表表名(列的字段名)
foreign key(字段名) references 主表表名(列的字段名)
不能向子表的外键所在列中插入父表对应列中不存在的元素!
[ SQL ]
插入到 stu (cno)值(7)中;
[ Err ]1452-无法添加或更新子行: 外键约束失败(‘ srs’)。‘ stu’,CONSTRAINT‘ stu _ ibfk _ 1‘ FOREIGN KEY (‘ cno’) REFERENCES‘ class’(‘ cno’))
[SQL]
insert into stu(cno) values(7);
[Err] 1452 - Cannot add or update a child row: a foreign key constraint fails (`srs`.`stu`, CONSTRAINT `stu_ibfk_1` FOREIGN KEY (`cno`) REFERENCES `class` (`cno`))
一个表中不限制外键的个数,但是子表中的列引用父表中的对应列,对应列 约束 应为主键约束或者唯一约束
解决方法:因为外键关联其他表的字段需要是主键,或者至少应满足唯一约束,因此加上唯一约束即可;
drop table if exists stu;
drop table if exists class;
create table class
(
cno int primary key auto_increment,
cname VARCHAR(5) unique
);
create table stu
(
sno int PRIMARY key auto_increment,
sname VARCHAR(10),
major VARCHAR(10),
cno int ,
cname VARCHAR(5),
FOREIGN key (cno) references class(cno),
foreign key (cname) references class(cname)
);
insert into class
(cname)
VALUES
('jd'),('jz'),('gk'),('gygc');
select * from class;
insert into stu
(sname,cno)
VALUES
('cwq',1),('ljb',2),('cyc',3);
insert into stu (cno) VALUES ('4');
select * from stu;