day03 MySQL数据库之主键与外键


day03 MySQL数据库之主键与外键

昨日内容回顾

针对库的基本SQL语句

# 增
	create database meng;
	
# 查
    show databases;
    shwo create database meng;
    
# 改	
	alter database meng charset='gbk';
	
# 删
	drop database meng;

针对表的基本SQL语句

# 增
	create table m1(id int,name char(4));
	
# 查
	show tables;
	show create table m1;
	desc m1;
	
# 改
	alter table m1 rename m2;
	
# 删
	drop table m1;
	
# 查询所在的库
 	select database();
 	
 # 切换库
 	use meng;

针对记录的基本SQL语句

# 增
	insert into m1 values(1,'db');
	
# 查
	select * from m1;
	seletc name from m1;
	
# 改
	update m1 set name='mqq' where id=1;
	
# 删
	delete from m1 where id=1;
	delete from m1;

存储引擎

# 查看引擎
	show engines;
	
# 一共有四个
	myisam:最早版本,存取速度快,但安全不足。
	innodb:存取速度比myisamman,但安全。
	memory:存储在内存,断电数据会消失。
	blackhole:黑洞,放到这里数据会消失
	
# 不同之处
	myisam:有三个文件
	innodb: 有两个文件
	memory:有一个文件
	blackhole:有一个文件
	
# 验证不同
	create table m1(id int) engine=myisam;
	

创建表的完整语法

create table 表名 (
	字段名称1 字段类型(数字) 约束条件,
	字段名称2 字段类型(数字) 约束条件,
	字段名称3 字段类型(数字) 约束条件
);

MySQL基本数据类型

# 整形
	tinyint
	smallint
	int
	bight
	
# 浮点型
	float
	double
	decimal
	
# 字符类型
	char:定长
	varchar:变长
	
# 数字的各自含义
	1、数字在数字类型中不是用来限制存储长度的,而是用来控制显示长度
	2、数字在其他类型中年都是用来显示存储长度的

sql_mode

# 模糊查询
	show variables like '%mode%';
	
char_length():查询字段长度
set session
set global

'strict_trans_tables':开启严格模式
'pad_char_to_full_length':取消底层优化

今日内容

1、基本数据类型之日期相关类型
2、基本数据类型之枚举与集合
3、约束条件
	unsigned
	zerofill
	not null
	default
	unique
	primary key
	auto_increment
	外键 # 重要

基本数据类型之日期相关类型

date		:年月日
datetime	 :年月日时分秒
time		:时分秒
year		:年

案例:
create table user(
	id int comment '编号',
    name varchar(255) comment '姓名',
    reg_time datetime comment '注册时间',
    birthday date comment '生日',
    study_time time comment '学习时间',
    born_year year comment '年份'
);
"""
字段也可以加类似于注释的说明
	comment
"""
# 此处先人工智能模拟 
	insert into user values(1,'meng','2000-11-11 11:11:11','2000-11-11','11:11:11','2000');

# 然后查询
	select * from user;

基本数据类型之枚举与集合

# 枚举
	1、多选一:提前定义好数据之后,后续录入只能录入定义好的内容之一。# 录入没有录入的内容,会报错。
	
    案例:
        create table m1 (
            id int,
            name char(6),
            gender enum('male','female')
        );
        insert into m1 values(1,'meng','male')  # 可以插入
        insert into m1 values(2,'mqq','bai')    # 错误,只能选录入的选项
    
# 集合
        多选多(包含多选一)

 	案例:
        create table m2 (
            id int,
            name char(6),
            hobbies set('lookbook','basketball','football')
        );
        insert into m2 values(1,'meng','lookbook')            # 可以选单个
        insert into m2 values(1,'meng','lookbook,football');  # 可以选多个,但不能选没有录入的爱好

插入方式

create table m3(id int,name varchar(16));
insert into m3(name) values('meng')  # 也可以用这种方式插入数据

"""
在插入数据的时候还可以指定表字段
	insert into m3(name) values('meng')
"""

约束条件

约束条件:约束条件相当于是在字段类型上添加的额外条件

1、unsigned:无符号
	id int unsigned
	
2、zerofill:0填充
	id int zerofill
	
3、not null:非空(不能为空)
	# 插入数据可以指定表字段
	create table m3(id int,name varchar(16));
	insert into m3(name) values('meng')  # 也可以用这种方式插入数据
	select * from m3;
	id     name
	NULL   meng
	
	# 必须填约束
	create table m4(id int,name char(6) no null);
	insert into m4(id) values(1);   # 会报错,不能为空
	insert into m4 values(1,'');    # 可以这样填,空也是字符


4、default:默认值(用户给了就用用户的,没给用默认的)
	create table m5(id int,name char(6) default '无敌');
	insert into m5(id) values(1);             # 没有写,默认是无敌
	insert into m5(id,name) values(2,'meng'); # 写了,就是写的内容
	select * from m5;
	id		name
	1		无敌
	2		meng
	
5、unique:唯一(保证字段在整个表里没有重复的数据)
	# 单列唯一:指定字段数据不能重复
		create table m6(id int,name char(6) unique);
		insert into m6 values(1,'meng'),(2,'meng')   # 重复数据会报错
		insert into m6 values(1,'meng'),(2,'bai')    # 成功
		
	# 联合唯一:多个字段数据一致为重复数据
		create table server (
			id int,
			host char(32),
			port char(32),
			unique(host,port)   # 两个数据一致会报错
		);
		
		insert into server values(1,'127.0.0.1','3333'),(2,'127.0.0.1','3335'),(3,'127.0.0.2','3335');  # 可以加入,必须是ip端口同时一致,才算是重复
		insert into server values(1,'127.0.0.1','3333'),(2,'127.0.0.1','3335'),(3,'127.0.0.2','3333');  # 报错,ip和字段一致为重复数据
		
6、primary key:主键
	(1)从约束条件上而言主键相当于no null + unique(非空且唯一)
	(2)主键的功能目前简单的理解为能够加快数据的查询速度相当于书的目录
		2.1、表中没有任何的主键和其他约束条件
			InnoDB默认会采用一个隐藏字段作为表的主键
		2.2、表中没有主键但是有非空且唯一的字段
			InnoDB会自动将该字段升级为主键
	(3)InnoDB存储引擎规定每张表都必须有且只有一个主键
	# 结论:每张表都必须要有一个id或者编号之类字段并且该字段就是主键
	
   # 单列主键
	验证:非空且唯一
        create table m7 (
            id int primary key,
            name char(6)
        );
        insert into m7(name) values('meng');      # 报错,不能为空
        insert into m7(id,name) values(1,'meng')  # 可以插入
        
	验证:自动升级为主键
		create table m8 (
			id int,
			name char(6),
			age int not null unique,   # 达成非空和唯一的条件自动升级为主键
			top int not null unique
		);
		desc m8;
		age   | int(11) | NO   | PRI | NULL   # PRT:主键
		
    # 多列主键(联合主键)
    	create table m9 (
    		id int,
    		age int,
    		name char(6),
    		primary key(id,age)   # 联合出是为一个主键
    	);
    	
    	
7、auto_increment:自增(配置主键一起使用,让主键能够自增)
	create table m10 (
		id int primary key auto_increment,
		name char(6)
	);
	insert into m10(name) values('meng'),('zhang'),('bai');  # 不用加主键,自动生成

主键自增特性

主键的自动是不会收到delete from删除操作的影响
truncate 既可以清空表数据也会重置主键值

验证:删除是否会影响自增
    delete from m10 where id=3;
    select * from m10;
    | id | name   
    |  1 | meng     # 删除不会影响
    |  3 | bai
    
验证:
	truncate m10;  # 会清空表数据,id重新开始    不建议用

外键

# 前戏
1.定义一张员工表
	id	name	age 	dep_name	dep_desc
    1	jason	18		外交部		搞外交
    2	kevin	28		教学部		教书育人
    3	tony	38		教学部		教书育人
    4	oscar	48		安保部		保家卫国
    5	jackson	58		财务部		发工资
"""
上述表不合理之处
	1.表内部数据混乱(可忽略)
	2.反复的录入重复数据(可忽略)
	3.修改数据太过繁琐  浪费磁盘空间(可忽略)
	4.极大地影响了操作数据的效率
"""
2.将上述表拆分成两张表
	id	name	age 
    1	jason	18
    2	kevin	28
    3	tony	38
    4	oscar	48
    5	jackson	58
	id	dep_name	dep_desc
    1	外交部		搞外交
    2	教学部		教书育人
    3	安保部		保家卫国
    4	财务部		发工资
"""拆分完之后解决了上述四个缺陷"""

# 外键
	用来记录表与表之间的关系

如何查找表关系

1.多对一
2.多对多
3.一对一
4.没有关系

"""查找表关系:换位思考"""
书籍表与出版社表
	1.先站在书籍表
    	问:一本书能够对应多个出版社
        答:不可以
    2.再站在出版社表
    	问:一个出版社能否对应多本书
        答:可以
    结论:一个可以一个不可以 表关系为"多对一"
   		那么外键字段建在"多"的一方
# 针对具有表关系的SQL建议先写普通字段 最后再考虑外键字段
    create table book(
        id int primary key auto_increment,
        title varchar(32),
        price int,
        pub_id int,
        foreign key(pub_id) references publish(id)  # book表中的pud_id和publish中的id是关联的
    );
    
    create table publish(
        id int primary key auto_increment,
        name varchar(32)
    );
    
    insert into publish(name) values('东方出版社'),('西方出版社');  # 先插入没有外键的表
    insert into book(title,price,pud_id) values('狼道',20,2);
    insert into book(title,price,pud_id) values('老人与海',30,1);  # pud_id关联着publish表的id
    select * from book;
    +----+--------------------------+-------+--------+
    | id | title                    | price | pud_id |
    +----+--------------------------+-------+--------+
    |  1 | 狼道                     |    20 |      2 |
    |  2 | 老人与海                 |    30 |      1 |
    +----+--------------------------+-------+--------+

外键约束

1.在创建表的时候需要先创建被关联表(没有外键的表)
2.在写入数据的时候也需要先写入被关联表(没有外键的表)
3.被关联表里面的数据无法直接删除和修改关联字段的操作

# 实时更新,删除
    on update cascade 
    on delete cascade

# 级联更新 级联删除
create table emp(
	id int primary key auto_increment,
    name varchar(32),
    age int,
    dep_id int,
    foreign key(dep_id) references dep(id) 
    on update cascade 
    on delete cascade
);

create table dep(
	id int primary key auto_increment,
    name varchar(32)
);
insert into dep(name) values('销售部'),('行政部'),('财政部');
insert into emp(name,age,dep_id) values('meng',18,3),('bai',19,2);
# 修改
update dep set id=200 where id=2;   # 实时修改

多对多

以书籍表与作者表为例
	1.先站在书籍表的基础之上
    	问:一本书能否对应多个作者
        答:可以
    2.在站在作者表的基础之上
    	问:一个作者能否对应多本书
         答:可以
    结论:两个都可以那么表关系就是"多对多"
        外键字段建在第三张关系表中
    

# 先写普通字段之后在考虑外键字段
'''错误的创建方式'''
create table book1(
	id int primary key auto_increment,
    title varchar(32),
    author_id int,
    foreign key(author_id) references author1(id) 
    on update cascade 
    on delete cascade
);
create table author1(
	id int primary key auto_increment,
    name varchar(32),
    book_id int,
    foreign key(book_id) references book1(id) 
    on update cascade 
    on delete cascade
);
'''正确的创建方式'''
create table book1(
	id int primary key auto_increment,
    title varchar(32)
);
create table author1(
	id int primary key auto_increment,
    name varchar(32)
);
create table book2author(
	id int primary key auto_increment,
    author_id int,
    foreign key(author_id) references author1(id) 
    on update cascade 
    on delete cascade,
    book_id int,
    foreign key(book_id) references book1(id) 
    on update cascade 
    on delete cascade
);