day46
day46
02.今日内容概要
约束条件
"""
1.unsigned 无负号
id int unsigned
2.zerofill 零填充
id int zerofill
3.not null 非空
name varchar(32) not null
4.default 默认值
name varchar(32) default 'jason'
"""
表与表之间建立关系(约束)(重点)
修改表的完整语法大全
复制表
03.约束条件
default默认值
# 补充知识点 插入数据的时候可以指定字段
use db3;
create table t1(
id int,
name char(16)
);
insert into t1(name,id) values('jason',1);
create table t2(
id int,
name char(16),
gender enum('male','female','others') default 'male'
);
insert into t2(id,name) values(1,'jason');
insert into t2 values(2,'egon','female');
unique唯一
# 单列唯一
create table t3(
id int unique,
name char(16)
);
insert into t3 values(1,'jason'),(1,'egon');
insert into t3 values(1,'jason'),(2,'egon')
# 联合唯一
"""
ip和port
单个都可以重复 但是加在一起必须是唯一的
"""
# 多列唯一
create table t4(
id int,
ip char(16),
port int,
unique(ip,port)
);
insert into t4 values(1,'127.0.0.1',8080);
insert into t4 values(2,'127.0.0.1',8081);
insert into t4 values(3,'127.0.0.2',8080);
insert into t4 values(1,'127.0.0.1',8080); # 报错
primary key主键
"""
1.单单从约束条件效果上看primary key等价于not null + unique
非空且唯一!!!
"""
create table t5(id int primary key);
insert into t5 values(null); # 报错
insert into t5 values(1),(1); # 报错
insert into t5 values(1),(2);
"""
2.它除了有约束效果之外 它还是innodb存储引擎组织数据的依据
InnoDB存储引擎在创建表的时候必须要有primary key
因为它类似于书的目录 能够帮助提示查询效率并且也是建表的依据
"""
# 特殊情况
"""
情况一
1.一张表中有且只有一个主键,如果你没有设置主键,那么会从上往下搜索直到遇到一个非空且唯一的字段将它自动升级为主键
"""
create table t6(
id int,
name char(16).
age int not null unique,
add char(32) not null unique
);
"""
情况二
2.如果表中没有主键也没有其他任何的非空且唯一字段,那么innodb会采用自己内部提供的一个隐藏字段作为主键,隐藏意味着你无法使用到它,就无法提示查询速度
"""
"""
情况三
3.一张表中通常都应该有一个主键字段 并且通常将id/uid/sid字段作为主键
"""
# 单个字段主键
create table t7(
id int primary key
name char(16)
);
# 联合主键(多个字段联合起来作为表的主键,本质还是一个主键)
create table t8(
id char(16),
port int,
primary key(ip,port)
):
"""
也意味着,以后我们在创建表的时候id字段一定要加primary key
"""
auto_increment
# 当编号特别多的时候,人为的缺维护太麻烦
# 自增(专门配合主键一起使用的 让主键能够自增)
create table t9(
id int primary key auto_increment,
name varchar(32)
);
insert into t9(name) values('jason'),('mike');
"""
# 注意auto_increment只能加在key建上,不能给普通字段加
结论
"""
以后再创建id(数据的唯一标识id、uid、sid)字段的时候
id int primary key auto_increment
"""
补充
# delete from :在删除表中数据的时候 主键自增不会停止
# truncate t1 :清空表数据并重置主键
04.外键简介
"""
1.定义一张员工表 表中有很多字段
id emp_name emp_gender dep_name dep_desc
1 jason male 外交部 搞外交
2 egon female 教学部 教书育人
3 tank male 教学部 教书育人
4 kevin male 教学部 教书育人
5 oscar female 技术部 技术能力有限部门
"""
# 上述表不合理之处
# 1.表内部数据混乱(可忽视)
# 2.浪费硬盘空间(可忽视)
# 3.数据的扩展性极差
# 如何优化?
"""
上述问题就类似于你将所有的代码都写在了一个py文件中
将上述表拆分成两张表
"""
被关联表和关联表
"""
被关联表
部门表
id dep_name dep_desc
1 外交部 搞外交
2 教学部 教书育人
3 技术部 技术能力有限部门
关联表
员工表
id emp_name emp_gender dep_id(外键字段)
1 jason male 1
2 egon female 2
3 tank male 2
4 kevin male 2
5 oscar female 3
6 linda female 4
"""
外键是什么?
# 外键就是用来帮助我们建立表与表之间关系
"""
外键用法:
1.设置在复杂的一方,也就是关联表,而少的就是被关联表
2.创建表的时候需要先建立被关联表
3.录入数据时,也要先录入被关联表
"""
05.一对多表关系
表关系
"""
表与表之间最多只有四种关系
一对多关系 # 海王和一堆路人甲
在mysql的关系中没有多对一这个说法
一对多和多对一,都叫一对多!
多对多关系 # 海王和海后
一对一关系 # 真爱
没有关系 # 路人甲和路人乙
"""
一对多关系
"""
判断表与表之间关系的时候,前期不熟悉的情况下,一定要按照我给你的建议
换位思考,分别站在两张表的角度考虑
员工表与部门表为例
先站员工表
一个员工能否对应多个部门(不能!)
再站部门表
一个部门能否拥有多个员工(可以)
得出结论
部门表与员工表表示单向的一对多
所以表关系就是一对多
"""
foreign key
1.一对多表关系,外键字段建在多的一方
2.在创建表的时候,一定要先建被关联表,再建关联表
3.在录入数据的时候,也要先录入被关联表
# SQL语句建立关系
create table dep(
id int primary key auto_increment,
dep_name char(16),
dep_desc char(32)
);
create table emp(
id int primary key auto_increment,
name char(16),
gender enum('male','female','others') default 'male',
dep_id int,
foreign key(dep_id) references dep(id)
);
insert into dep(dep_name,dep_desc) values('sb教学部','教书育人'),('外交部','多人外交'),('nb技术部','技术能力有限 部门');
insert into emp(name,dep_id) values('jason',2),('egon',1),('tank',1),('kevin',3);
select * from dep;
select * from emp;
# 修改dep表里面的id字段
update dep set id=200 where id=2;
# 删除dep表里面的数据(发现报错,因为加了外键)
delete from dep;
"""
# 正确操作,但是操作过于繁琐
delete from emp where id=4;
select * from emp;
update dep set id=300 where id=3;
select * from dep;
"""
级联更新、级联删除
"""
更新就同步更新
删除就同步删除
"""
create table dep(
id int primary key auto_increment,
dep_name char(16),
dep_desc char(32)
);
create table emp(
id int primary key auto_increment,
name char(16),
gender enum('male','female','others') default 'male',
dep_id int,
foreign key(dep_id) references dep(id)
on update cascade # 同步更新
on delete cascade # 同步删除
);
insert into dep(dep_name,dep_desc) values('sb教学部','教书育人'),('外交部','多人外交'),('nb技术部','技术能力有限 部门');
insert into emp(name,dep_id) values('jason',2),('egon',1),('tank',1),('kevin',3);
select * from dep;
select * from emp;
update dep set id=300 where id=3; # 修改dep部门表中的id,emp中会同步更新
select * from dep;
select * from emp;
06.多对多表关系
"""
图书表和作者表
"""
create table book(
id int primary key auto_increment,
title varchar(32),
price int,
author_id int,
foreign key(author_id) references author(id)
on update cascade # 同步更新
on delete cascade # 同步删除
);
create table author(
id int primary key auto_increment,
name varchar(32),
age int,
book_id int,
foreign key(book_id) references book(id)
on update cascade # 同步更新
on delete cascade # 同步删除
);
"""
按照上述的方式创建 一个都别想成功!!!
因为建立book表时,要先建立被关联表author,建立author表要先建立被关联表book,所以两个表一个也建不成。
"""
多对多关系
# 两个表本身并无关联,两个表和中间表有关联,建立第三张表
create table book(
id int primary key auto_increment,
title varchar(32),
price int
);
create table author(
id int primary key auto_increment,
name varchar(32),
age int
);
create table book2author(
id int primary key auto_increment,
author_id int,
book_id int,
foreign key(author_id) references author(id)
on update cascade # 同步更新
on delete cascade, # 同步删除,注意这里有两个外键,中间用逗号隔开
foreign key(book_id) references book(id)
on update cascade # 同步更新
on delete cascade # 同步删除
);
insert into book(title,price) values("降龙十八掌",999),("九阴真经",888),("九阳神功",666);
insert into author(name,age) values("egon",23),("tank",19),("jason",18);
insert into book2author(author_id,book_id) values(1,1),(1,2),(2,2),(2,3),(3,3),(3,1);
select * from book;
select * from author;
select * from book2author;
update book set id=100 where id=1; # 修改book表中id
07.一对一表关系
"""
id name age addr phone hobby email........
如果一个表的字段特别多 每次查询又不是所有的字段都能用得到
将表一分为二
用户表
用户表
id name age
用户详情表
id addr phone hobby email........
站在用户表
一个用户能否对应多个用户详情 不能!!!
站在详情表
一个详情能否属于多个用户 不能!!!
结论:单向的一对多都不成立 那么这个时候两者之间的表关系
就是一对一
或者没有关系(好判断)
客户表和学生表
在你们报名之前你们是客户端
报名之后是学生(期间有一些客户不会报名)
"""
一对一关系
# 一对一:外键字段建在任意一方都可以,但是推荐你建在查询频率比较高的表中
# 作者详情表
create table authordetail(
id int primary key auto_increment,
phone int,
addr varchar(64)
);
# 作者信息表
create table author(
id int primary key auto_increment,
name varchar(32),
age int,
authordetail_id int unique, # 作者详情id字段为什么要唯一,因为,如果不唯一,那么随便insert一个作者,作者详情都可以互串,不合理。每个作者只能对应一个详情
foreign key(authordetail_id) references authordetail(id)
on update cascade # 同步更新
on delete cascade # 同步删除
);
insert into authordetail(id,phone,addr) values(1,110,"上海");
insert into author(name,age,authordetail_id) values("mike",23,1);
08.表关系总结
"""
表关系的建立需要用到foreign key
一对多
外键字段建在多的一方
多对多
自己开设第三张存储
一对一
建在任意一方都可以 但是推荐你建在查询频率较高的表中
判断表之间关系的方式
换位思考!!!
员工与部门
图书与作者
作者与作者详情
"""
09.修改表
# Mysql对大小写是不敏感的
"""
1.修改表名
alter table 表名 rename 新表名 ;
2.增加字段
alter table 表名 add 字段名 字段类型(宽度) 约束条件
alter table 表名 add 字段名 字段类型(宽度) 约束条件 first
alter table 表名 add 字段名 字段类型(宽度) 约束条件 after 地段名;
3.删除字段
alter table 表名 drop 字段名;
4.修改字段
alter table 表名 modify 字段名 字段类型(宽度) 约束条件;
alter table 表名 change 旧字段名 新字段名 字段类型(宽度) 约束条件;
"""
10.复制表
# 查询语句执行的结果也是一张表,可以看成虚拟表
show tables;
# 复制表结构+记录 (key不会复制: 主键、外键和索引)
create table new_service select * from service; # 这里as省略了
# 只拷贝表结构(不包含键),# 因为条件(1=2)为假,没有记录
create table new1_service select * from service where 1=2;
# 拷贝结构包含各种key(备份表结构,索引,主键)
create table t4 like employees;