46-mysql-约束条件、表与表之间关系、修改表的完整语法、复制表

今日内容概要

  • 约束条件
  • 表与表之间建关系(约束)(重点)
  • 修改表的完整语法大全
  • 复制表
  • 作业布置(如何判断表关系及如何建立表关系)

今日内容详细

约束条件

default默认值

# 补充知识点  插入数据的时候可以指定字段
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(4,'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,
    addr char(32) not null unique
);

# 2 如果表中没有主键也没有其他任何的非空且唯一字段 那么Innodb会采用自己内部提供的一个隐藏字段作为主键,隐藏意味着你无法使用到它 就无法提示查询速度

# 3 一张表中通常都应该有一个主键字段 并且通常将id/uid/sid字段作为主键
# 单个字段主键
create table t5(
    id int primary key
	name char(16)
);
# 联合主键(多个字段联合起来作为表的主键 本质还是一个主键)
create table t7(
    ip char(16),
    port int,
    primary key(ip,port)
);

"""
也意味着 以后我们在创建表的时候id字段一定要加primary key
"""

auto_increment自增

# 当编号特别多的时候 人为的去维护太麻烦
create table t8(
	id int primary key auto_increment,
    name char(16)
);
insert into t8(name) values('jason'),('egon'),('kevin');

# 注意auto_increment通常都是加在主键上的 不能给普通字段加
create table t9(
	id int primary key auto_increment,
    name char(16),
    cid int auto_increment
);
ERROR 1075 (42000): Incorrect table definition; there can be only one auto column and it must be defined as a key

结论

"""
以后在创建表的id(数据的唯一标识id、uid、sid)字段的时候
id int primary key auto_increment
"""

补充

delete from t1  删除表中数据后 主键的自增不会停止

truncate t1  清空表数据并且重置主键

表与表之间建关系

"""
定义一张员工表 表中有很多字段
id name gender dep_name dep_desc
"""
# 1 该表的组织结构不是很清晰(可忽视)
# 2 浪费硬盘空间(可忽视)
# 3 数据的扩展性极差(无法忽视的)

# 如何优化?
"""上述问题就类似于你将所有的代码都写在了一个py文件中"""
将员工表拆分  员工表和部门表

外键

"""
外键就是用来帮助我们建立表与表之间关系的
foreign key
"""

表关系

"""
表与表之间最多只有四种关系
	一对多关系
		在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);


# 修改dep表里面的id字段
update dep set id=200 where id=2;  不行
# 删除dep表里面的数据
delete from dep;  不行

# 1 先删除教学部对应的员工数据 之后再删除部门
	操作太过繁琐
    
# 2 真正做到数据之间有关系
	更新就同步更新
    删除就同步删除
"""
级联更新   >>>   同步更新
级联删除   >>>   同步删除
"""
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);

多对多

"""
图书表和作者表
"""
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  # 同步删除
);
"""
按照上述的方式创建 一个都别想成功!!!
其实我们只是想记录书籍和作者的关系
针对多对多字段表关系 不能在两张原有的表中创建外键
需要你单独再开设一张 专门用来存储两张表数据之间的关系
"""
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  # 同步删除
);

一对一

"""
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,
    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 字段名 字段类型(宽度)  约束条件 after 字段名;

3 删除字段
	alter table 表名 drop 字段名;

4 修改字段
	alter table 表名 modify 字段名 字段类型(宽度) 约束条件;
	
	alter table 表名 change 旧字段名 新字段名 字段类型(宽度) 约束条件;
	
"""

复制表(了解)

"""
我们sql语句查询的结果其实也是一张虚拟表
"""
create table 表名 select * from 旧表;  不能复制主键 外键 ...

create table new_dep2 select * from dep where id>3;

作业布置

练习:账号信息表,用户组,主机表,主机组

#用户表
create table user(
id int not null unique auto_increment,
username varchar(20) not null,
password varchar(50) not null,
primary key(username,password)
);

#用户组表
create table usergroup(
id int primary key auto_increment,
groupname varchar(20) not null unique
);

#主机表
create table host(
id int primary key auto_increment,
ip char(15) not null unique default '127.0.0.1'
);

#业务线表
create table business(
id int primary key auto_increment,
business varchar(20) not null unique
);

#建关系:user与usergroup

create table user2usergroup(
id int not null unique auto_increment,
user_id int not null,
group_id int not null,
primary key(user_id,group_id),
foreign key(user_id) references user(id),
foreign key(group_id) references usergroup(id)
);

#建关系:host与business
create table host2business(
id int not null unique auto_increment,
host_id int not null,
business_id int not null,
primary key(host_id,business_id),
foreign key(host_id) references host(id),
foreign key(business_id) references business(id)
);

#建关系:user与host
create table user2host(
id int not null unique auto_increment,
user_id int not null,
host_id int not null,
primary key(user_id,host_id),
foreign key(user_id) references user(id),
foreign key(host_id) references host(id)
);

练习:

# 班级表
cid	caption
# 学生表
sid sname gender class_id
# 老师表
tid	tname
# 课程表
cid	cname	teacher_id
# 成绩表
sid	student_id course_id number

每日测验

  • 你所知道的约束条件有哪些
  • 表与表之间关系有几种,如何判断
  • 创建上述表关系的SQL语法如何书写

内容回顾

  • 约束条件

    """
    not null
    zerofill
    unsigned
    
    default
    	gender enum('male','female','others') default 'male'
    
    unique
    	单列唯一
    		id int unique
    	联合唯一
    		ip int,
    		port int,
    		unique(ip,port)
    
    primary key  主键
    	1.在限制效果上跟not null + unique一致
    		id int primary key
    	2.它还是Innodb存储引擎组织数据的依据 
    		1.使用Innodb规定一张表中必须有且只有一个主键
    		2.当你没有设置主键的时候
    			1.从上往下查找非空且唯一的自动升级为主键
    			2.如果什么都没有设置 那么就会使用内部隐藏的字段作为主键
    				无法使用到
    			3.一张表中通常都应该有一个id字段并且该字段应该是主键
    
    auto_increment
    	自增列
    	该限制条件只能加在被设置成键的字段上 并且一般都是跟主键一起使用
    	id int primary key auto_increment
    """
    
    针对主键补充知识点
    	你在将表中数据删除的时候 主键的自增并不会停止 
    
    truncate 清空数据并重置主键
    
  • 外键

    """
    外键就是用来在代码层面真正的实现表与表之间的关系
    foreign key
    """
    
  • 表与表之间建关系

    """
    表与表之间的关系只有三种
    	一对多
    		在MySQL中 一对多和多对一 都叫一对多
            外键字段建在多的那一方
    	多对多
    		关系无需建外键 而是单独开设一张表专门用来存储关系
    	一对一
    		外键字段建在任意一方均可
    		但是推荐你建在查询频率较高的表中
    """
    """判断表关系前期不熟练一定要换位思考 慢慢问自己"""
    
    # 一对多判断
    图书与出版社
    	先站在图书表
        	一本书能否被多个出版社出版			版权问题 不可以!!!
        再站在出版社表
        	一个出版社能否出版多本书			可以
        结论:单向的一对多成立 那么表关系就是一对多  书是多的一方
    
    外键带来的约束
    	1.在创建表的时候一定要先创建被关联表
        2.在插入数据的时候也要先插入被关联表
        3.操作数据的时候 会出现多种限制  同步更新 同步删除
       	create table publish(
        	id ...
        );
        create table book(
        	id ...
            publish_id int,
            foreign key(publish_id) references publish(id)
            on update cascade  # 同步更新
            on delete cascade  # 同步删除
        );
    
    # 多对多
    	图书和作者
        	先站在图书表
            	一本书可不可以有多个作者	可以!!!
            再站在作者表
            	一个作者能不能写多本书		 可以!!!
        	结论:图书和作者是双向的一对多 那么表关系就是 多对多
    
            一定要单独开设一张新的表存储表关系
        create table book(
        	id ...
        )
        create table author(
        	id ...
        )
        create table book2author(
        	id ...
            book_id int,
            author_id int,
            foreign key(book_id) references book(id)
            on update cascade  # 同步更新
            on delete cascade,  # 同步删除
            foreign key(author_id) references author(id)
            on update cascade  # 同步更新
            on delete cascade,  # 同步删除
        )
    # 一对一
    	qq用户表
        客户与学生表
        """
        	当你一张表中的数据并不都是频率需要用到的情况 但是字段有特别的多
        	那么这个时候你就应该考虑分表 然后做一对一的关联
        	节省查询时间和传输时间
        """
        作者与作者详情
        	无论站在哪一方都不能成立一对多
            双方一对多都不成立那么表关系
            	一对一
                没有关系
        create table author(
        	id ...
            authordetail_id int unique,
            foreign key(authordetail_id) references authordetail(id)
            on update cascade  # 同步更新
            on delete cascade,  # 同步删除
        );
        create tabel authordetail(
        	id ...
        );
    

    补充

    """
    表与表之间如果有关系的话 可以有两种建立联系的方式
    	1.就是通过外键强制性的建立关系
    
    	2.就是自己通过sql语句逻辑层面上建立关系
    		delete from emp where id=1;
    		delete from dep where id=1;
    
    	创建外键会消耗一定的资源 并且增加了表与表之间的耦合度
    	在实际项目中 如果表特别多 其实可以不做任何外键处理 直接
    	通过sql语句来建立逻辑层面上的关系
    	到底用不用外键取决于实际项目需求
    """
    
  • 修改表

    """
    alter table t1 rename new_t1;
    
    alter table t1 add 字段名 ...;
    alter table t1 add 字段名 ... first;
    alter table t1 add 字段名 ... after 旧字段;
    
    alter table t1 drop 字段名;
    
    modify一般都是用来修改字段的字段类型 约束条件等 不能修改字段名
    alter table t1 modify 字段名 数据类型(宽度) 约束条件
    
    alter table t1 change 旧字段名 新字段名 ...;
    """
    
  • 复制表

    """
    我们sql语句查询出来的结果也可以看成是一张表(虚拟表)
    言外之意 就是针对这个查询结果还可以继续用查询表的语法继续操作该虚拟表
    """
 
posted @ 2020-07-05 13:43  电竞杰森斯坦森  阅读(204)  评论(0编辑  收藏  举报