5.5
昨日回顾
-
存储引擎
show engines
-
创建表的完整语法
create table t1( name char(4) not null, id int )
-
严格模式:使用数据库的时候尽量让数据库少干活
-
基本数据类型
-
整型:tinyint,int,bigint,默认都有符号
-
浮点型:float,double,decimal
精确度 float < double < decimal
-
字符类型
char定长,varchar变长
-
日期
-
枚举与集合
-
今日内容
重要
- 约束条件
- 表与表之间建立关系(约束)
- 修改表的语法
- 复制表
- 作业:如何判断表关系及建立表关系
约束条件
default 默认值
# 插入数据的时候指定字段
create table t1(id int, name char(8));
insert into t1(name,id) values('aaa',2020);
# 创建表的时候给字段设置默认值
create table t2(id int, name char(8), gender enum('male','female') default 'male');
# 字段类型后面不加逗号,跟默认值
insert into t2(id,name) values(2021,'bbb');
# 这样,默认的gender就是male
unique 唯一
# 单列唯一
create table t3(id int unique, name char(8));
insert into t3 values(1, 'aaa'),(1, 'bbb');
# 报错,显示 id 字段唯一
insert into t3 values(1, 'ccc'),(2, 'ddd');
# 正常添加
# 联合唯一
# 例,ip和端口,单个可以重复,但是加载到以前必须是唯一的
create table t4(
id int,
ip char(16),
port int,
unique(ip,port)
);
# 在最后,用unique加括号,把联合唯一的字段放进去
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(4, '127.0.0.1', 8080);
# 报错,ip和端口都与 1 重复
primary key 主键
重要
单从约束效果来看,等价于 not null + unique
# 创建表,id为主键
create table t3(id int primary key);
insert into t5 values(1),(1);
insert into t5 values(null);
# 报错
insert into t5 values(1),(2);
# 正常创建
除了有约束效果以外,他还是innodb存储引擎组织数据的依据,innodb创建表的时候必须要有primary key
类似于书的目录,能够帮助提示查询效率,并且是建表的依据
那之前没有用主键是怎么建表的呢?
- 一张表有且只有一个主键,如果没有设置主键,那么回从上往下搜索直到遇到一个非空且唯一的字段,自动将其升级为主键
- 如果表中没有主键也没有其他任何的非空且唯一字段,那么innodb会采用自己内部提供的一个隐藏字段作为主键。这个隐藏的字段我们无法使用
- 通常一张表应该有一个主键字段,通常叫做id
联合主键:了解
create table t6(
ip char(16),
port int,
primary key(ip,port)
);
以后创建表,都必须给id加上主键
auto_increment 自增
当编号特别多的时候,设置每次新增数据,id自动+1
create table t8(
id int rimary key auto_increment,
name char(16)
);
# 创建表,id自增
insert into1 t8(name) vlues('aaa'),('bbb'),('ccc');
# 插入后查看,既有name,又有id
# auto_increment 通常都是加在主键上的,编号序号一类,不能给普通字段加
这个约束条件内部有一个计数器,就算delete from 把数据删掉了,主键的自增序号也不会删除,而是会从当前计数再往下自增
delete from t8; # 删除表中数据,没有删除自增序号
truncate t8; # 清空表数据,并重置自增计数
表与表间建立关系
对普通的表进行拆分,将拆分的表建立联系
表与表之间的关系
# 表与表之间最多只有4种关系
# 1. 一对多关系
# 2. 多对多关系
# 3. 一对一关系
# 在确定表关系的时候要换位思考:在两边的表考虑是对应一个或多个
# 一个部门有多个员工,一个员工只属于一个部门:单向的一对多关系
外键:用来帮助我们建立表与表之间关系的字段:foreign key
一对多关系
foreign key
# 建部门表
create table dep(
id int promary key auto_increment,
dep_name char(16)
);
# 建员工表
create table emp(
id int promary key auto_increment,
emp_name char(16),
gender enum('male','female') default 'male'
dep_id int,
foreign key(dep_id) references dep(id)
# 本表的dep_id字段是外键字段,与dep表的id有联系
);
# 先插入部门数据
insert into dep(dep_name) values('外交部'),('技术部');
# 插入员工数据
insert into emp(emp_name, dep_id) values('aaa',1),('bbb',2);
foreign key 规范
- 一对多关系表,外键字段建在 多 的一边
- 在创建表的时候要先建被关联表
- 在录入数据的时候必须先录入被关联表
- 当约束存在,想要修改被关联的表,不能直接操作,要想实现同步删除或更新,另外声明
修改被关联表
on update cascade
# 1. 先修改关联的数据,再修改被关联的数据:操作太频繁,不用
# 2. 真正做到表间有关系:更新就同部更新,删除就同部删除
# 级联更新,级联删除(同部):在创建表的时候需要声明额外的参数
create table emp(
id int promary key auto_increment,
emp_name char(16),
gender enum('male','female') default 'male'
dep_id int,
foreign key(dep_id) references dep(id)
on update cascade # 同部更新
on delete cascade # 同步删除
);
# 修改dep表,id变成200
update dep set id=200 where id=2;
select* from dep
select* from emp
# 此时查看emp表,关联了id=2的数据id也变成200了。如果删除id=200,那么员工表关联id=200的也被删除
多对多关系
例:书籍与作者,一本书有多个作者,一个作者不止写一本书,多对多关系
# 创建书籍表
create table book(
id int promary key auto_increment,
title varcahr(32),
price int
);
# 创建作者表
create table author(
id int promary key auto_increment,
name varchar(32),
book_id int,
)
# 创建关系连接表
create table book2author(
id int promary key auto_increment,
author_id int,
book_id int,
foreign key(author_id) references author(id)
on update cascade
on delete cascade,
# 作者id
foreign key(book_id) references book(id)
on update cascade
on delete cascade
# 书本id
)
# 按照一对多的思想建表,谁都别想建成,对于这种场景,应该另外建一张表 book2author,专门存储表之间的关系
# 作者与关系表表和书与关系表book2author都是一对多的关系
#
一对一关系
用户独有的属性:昵称,年龄,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,
foreign key(authordetail_id) references authordetail(id)
on update cascade # 同步更新
on delete cascade # 同步删除
)
总结
- 表关系的建立要用到 foreign key
- 一对多:外键字段建在多的一方
- 多对多:开设另外一张关系表
- 一对一:建立在任意以访,推荐建在查询频率高的表中
- 判断表之间关系的方式:换位思考
修改表
MYSQL不区分大小写
# 1. 修改表名
alter table 表名 rename 新表名;
# 2. 增加字段
alter table 表明 add 字段名 字段类型(宽度) 约束条件; # 默认在最后面添加
alter table 表明 add 字段名 字段类型(宽度) 约束条件 first; # 添加到最前面
alter table 表明 add 字段名 字段类型(宽度) 约束条件 last; # 添加在最后面;
# 3. 删除字段
alter table 表名 drop 字段名;
# 4. 修改字段属性
alter table 表名 modify 字段名 字段类型(宽度) 约束条件;
# 修改字段名
alter table 表名 change 旧字段名 新字段名 字段类型(宽度) 约束条件;
复制表
MYSQL每次查询得到的结果也是一张表:内存中的一张虚拟表
# 1.
create table new_table select * from t1;
# create table 新表名 select * from 旧表名;
# 这样只能复制了表的结构和数据,但是不能复制主键外键索引一类属性
# 如果复制的约束条件结果中没有数据,得到一个没有数据的空表