一、储存数据的演变
-
随意的存到一个文件中、数据格式也是千差万别的完全取决于我们自己
- 虽然不同的人可以根据自己喜欢的格式进行存储,但是代码给别读取的话就会变得困难
-
软件开发目录规范
- 限制了存储数据的具体位置
'''
bin
conf
core
dbd
lib
readme
'''
1、数据库的本质
'''
数据库的本质就是一款基于网络通信的应用程序
其实每个人都可以开发一款数据库软件,因为它仅仅就是一个基于网络通信的应用程序
也就意味着数据库软件其实有很多,如:
关系型数据库:
MySQL、oracle、db2、access、SQL server
菲关系数据库:
redis、MongoDB、memcache
'''
# 关系型:
1.数据之间彼此有关系或者拘束,如:
前女友表和男生表(一个男生对应着多个前女友)
2.储存数据的表现形式通常是以表格的方式储存
name password hobby
vyj 132 eatbasketball
zcy 123 play game
每个字段还可以设置储存的数据类型的限制
如名字只能储存字符串数据类型
#非关系型:
储存的数据都是以key,value的形式
MySQL
'''
任何基于网络通信的应用程序底层都是socket
服务器:
-基于socket通信
-收发消息
客户端:
-基于socket通信
'''
mysql不单单支持MySQL自己的客户端app还支持其他编程语言来充当客户端操作
如何解决语言沟通的障碍:
#1、 让服务端兼容所有的语言(一个人精通多国语言)
#2、 采用统一的语言(SQL语句)
- 重要概念介绍
'''
库 对应 文件夹
表 对应 文件
记录 对应 文件里面一行行的数据
表头指的是表格的第一行的字段
字段 name,password,hobby
表单就是表头下面的所有数据
'''
MySQL的安装
'''
注意事项:不要随意的更新版本,因为新版本可能会出现各种问题(可能你原来的mysql可以运行但是你更新版本之后可能就会崩溃)
'''
#MySQL版本有(5.6,5.7,8.0)
mysql官网:https://www.mysql.com/
各个版本的sql语句一般来说都是一样的
1、在mysql官网中下载mysql到本地
注意:在公司中是有两个程序,一个是服务端,一个是客户端,修改数据需要客户端访问服务端,服务端是专门的在一台服务器上运行,所有人都是基于网络连接服务器来实现修改数据库
2、mysql服务端和客户端
'''
服务端
mysqld.exe
客户端
mysql.exe
'''
注意
'''
在前期配置MySQL的时候 cmd终端尽量以管理员的身份运行
win+r 输入cmd 进入的是普通用户终端,在一些命令是无法执行的
输入cmd右键 以管理员身份运行
'''
启动
- 在cmd切换到mysqld所在的bin目录下,然后输入mysqld即可
- 保留原来的cmd窗口重新打开一个
'''
常见软件的默认端口号(需要背)
MSQL 3306
redis 6379
MongoDB 27017
django 8000
flask 5000
Tomcat 8080
mysql第一次以管理员身份进入是没有密码的,直接回车即可
客户端连接服务端完整命令
mysql -h 127.0.0.1 -p 3306 -uroot -p
如果你连接的地址为本地地址127.0.0.1那么可以简写为
mysql -uroot -p
当你输入的指令不对,但是不想要服务器执行返回报错的话,那么可以在后面输入\c取消,不需要使用分号
fadfaf \c
客户端退出指令(不需要使用分号结束)
quit
exit
当你的在连接服务端的时候,可以直接输入mysql来直接mysql,但是这个时候的访问为游客模式,很多功能都不能使用
'''
SQL语句初识
'''
1、MySQL中的sql语句是以分号作为结束的标志
2、基本命令
show databases; 查看所有的数据库名
'''
环境变量配置及系统服务制作
小知识点补充
'''
1、如何查看当前具体进程
tasklist #查看所有的进程
tasklist |findstr mysqld #指定查看mysql服务端的进程
2、如何杀死具体进程(只有在管理员身份运行cmd才能成功)
tasklist /F /PID PID号
'''
环境变量配置
'''
每次启动mysqld需要先切到对应的文件路径下才能操作太繁琐
将mysqld所在的文件路径添加到系统环境变量中
'''
但是完成上面的还是需要两个cmd窗口来运行,所以可以
将mysqld服务端制作成系统服务(开机自启)
'''
查看当前计算机的运行进程数(在win+r中输入)
services.msc
先将服务器初始化
mysqld --initialize-insecure
将mysql制作成服务端
mysqld --install #mysqld为服务端启动文件
移除myql系统服务
mysqld --remove
'''
设置密码
'''
mysqladmin -uroot -p 原密码 password 新密码
在终端中直接运行即可,不需要进入mysql
'''
破解密码
如果忘记了密码的话那么就需要重置密码
'''
你可以将mysql获取用户名和密码校验的功能看成是一个装饰器
装饰在了客户端请求访问的功能上
我们如果将该装饰器移除,那么mysql服务端就不会校验用户名和密码了
'''
# 1 、先关闭当前mysql服务端
命令行的方式启动(让mysql跳过用户名和密码验证功能)
mysqld --skip -grant -tables #这个是启动服务器使用的指令,这样之后就不会使用密码了
# 2、直接以无密码的方式连接
mysql -uroot -p 直接回车
# 3、修改当前用户的密码
update mysql.uer set password=password(密码) where user='root' and host='localhost'
#后面的where 表示的是用户名为root 端口名为localhost
#password()是把里面的数据加密
'''
真正储存用户表的密码字段,储存的肯定是密文
只有用户自己知道明文是什么,其他人都不知道,这样比较安全
密码比对也只能比对密文
'''
# 4、立刻将修改数据刷到硬盘这
flush privileges;
# 5、关闭当前服务器,然后以正常校验授权表的形式启动
统一编码
- mysql默认的配置文件
'''
my-defaule.ini
ini结尾的一般都是配置文件
程序启动一般先会加载配置文件中的配置
'''
[mysqld] #一旦服务端启动的时候会立刻加载下面的配置
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
[mysql]#一旦客户端启动立刻加载下面的配置
...
[client] #其他语言的客户端
#需要新建一个配置文件
#修改配置文件后一定要重启服务才能生效
#统一编码的配置 无需掌握 直接拷贝
#可以将用户的账户和密码加入配置文件中
'''
[mysqld]
#设置3306端口
datadir=D:\\mysql-5.7.34-winx64\\data
port = 3306
# 设置mysql的安装目录
basedir=D:\\mysql-5.7.34-winx64
# 允许最大连接数
max_connections=200
# 服务端使用的字符集默认为8比特编码的latin1字符集
character-set-server=utf8
default-storage-engine=INNODB
collation-server=utf8_general_ci
[mysql]
default-character-set=utf8
[client]
default-character-set=utf8
[mysql]
# 设置mysql客户端默认字符集
default-character-set=utf8
MySQL操作
ps:大部分程序的业务逻辑其实都是增删改查
针对库的增删改查(文件夹)
#增
create databases 数据库名;
create databases lb charset='gbk';#后面的表示指定数据库的编码格式
#查
show databases;#表示查找所有的数据库名
show create databse 数据库名;#表示查找单个数据库
#改
alter database 要修改的数据库名 charset='编码格式';#修改数据库的编码格式
#删
drop database 要被删除的数据库名; #删除指定的数据库
针对表的增删改查(文件)
'''
在操作(文件)的时候,需要指定所在的库(文件夹)
'''
# 查看当前所在的库的名字
select database();
# 切换库
use db1;
# 增
create table t1(id int,name char(4)) #id和name表示的表头的数据,int和char表示的是数据的类型,char里面的数据为数据的长度
show create table 被查询的表名;#表示在数据库里面查询指定表的名字
describe 被查询的表名; #也是查询表的信息,但是格式和上面的不一样,支持简写可以写成 desc 被查询表名
#改
alter table 被修改表单 modify name char(16);#表示修改表单数据name为16位的字符类型
#删
drop table 被删除的表名; #删除数据库里面指定的表的名字
#小知识可以用指定路径来创建表
#在t1里面直接创建l3表
create table t1.l3(id int) #但是记住要指定表头
针对数据的增删改查(一行行数据)
'''
一定先有库,有表,最后才能操作记录
'''
#增
insert into t1 values(1,'1')#表示在t1表中添加两个 1 , '1'的数据
insert into t1 values(1,'1'),(2,'3') #添加多个数据的书写方式
#查
select * from t1; #t1表示被查询表的名字,*表示所有的数据名,数据较多不建议使用、
select id from t1;#表示的是查询表所以数据的id信息、
#改
update t1 set name='DSB' where id >1;#表示的是修改t1表里id大于1的name字段里面的数据为'DSB'
#删
delete from t1 where id>1;#表示的是删除表里面id大于1的所有数据、
delete from t1 where name ='1' #表示的是删除t1表里面name属性为1底的数据
# 将表所有的数据清空
delete from t1;# t1表示别清空数据的表的名字
#当表里面的数据过多的时候可以使用\G分行展示
创建表的完整语法
#语法
create table 表名(
字段名1 类型(宽度) 约束条件,
字段名2 类型(宽度) 约束条件,
字段名3 类型(宽度) 约束条件
)
#注意
1 、在同一张表中字段名不能重复
2、宽度和约束条件是可选的(可写可不写)而字段名和字段类型是必须的约束条件写的话 也支持写多个如:
字段名1 类型(宽度) 约束条件1 约束条件2 ...,
create table t5(id); #这个语句在mysql中运行会直接报错因为他没有指定id的数据类型
3、最后一行不能有逗号
create table t6(
id int,
name char
);
'''补充'''
#宽度
一般情况下指的是对存储数据的限制
create table t7(name char); #char的默认长度为1
insert into t7 values('libai');
针对不同的版本会出现不同的效果
5.6版本默认没有开启严格模式,规定只能存储一个字符,你给了多少个字符,那么我会自动帮你截取
5.7版本级以上或者开启了严格模式,那么规定只能存几个就不能超,一旦超出范围就会立刻报错
'''严格模式到底该不该开呢'''
MySQL5.7版本默认都是开启严格模式的
使用数据库准则:
能尽量少的让数据库干活就尽量少一点,不要给数据库增加额外的压力(所以一般开严格模式)
# 约束条件 null not null 设定数据不能为空
create table t8(id int ,name char not null);#这个数据里面的name属性是不能为空的
'''宽度和约束条件到底是什么关系
宽度是用来限制数据的存储
约束条件是在宽度的基础之上增加的额外的约束
'''
严格模式
# 如何查看严格模式
show variables like "%mode"; #like 表示查询的语句,而%mode表示模糊匹配匹配的数据,和Python的正则匹配一样 里面的variables表示查询的东西
#如你想要查询对应的表可以写成 show tables like "%mysql";
模糊匹配/查询
关键字 like
%:匹配任意多个字符
_:匹配任意单个字符
# 修改严格模式
set session #只在当前窗口有效
set global #全局有效
set global sql_mode ='STRICT_TRANS_TABLES' #表示把数据库的模式转换为严格模式(注意5.7版本以上默认就为严格模式所以不需要转换)
set global sql_mode ='NO_ENGINE_SUBSTITUTION'#表示包数据类型转换为非严格模式
#修改完之后重新进入mysql就会生效
注意在严格模式下如果存入数据过大会直接报错,而不是像非严格模式下一样会切割你的数据
基本数据类型
整型
-
分类
tinyint(范围:(-128,127),(0,255))
smallint(范围:(-32768,32767),(0,65535))
mediumint(范围:(-8388608,8388607),(0,16777215))
int或integer(范围:(-2147483648,2147483647),(0,4294967295))
bigint(范围:(-9233372036854775808,9233372036854775807),(0,18446744073709551615))
-
作用
储存年龄、等级、id、号码等等
'''
以TINYINT
是否有符号
超出会如何
'''
create table t9(id tinyint);
insert into t9 values(-129,257);#当数据超出限制只存最大的接收值
# 约束条件之unsigned 无符号
create table t10(id tinyint unsigned);
create table t11(id int)
#int 默认也是带符号的
# 整型默认情况下都是带有符号的
# 针对整型 括号内的宽度到底是干嘛的
create table t12(id int(8) zerofill);#如果想看到数据里面的0补全可以在后面加zerofill
insert into t12 values(123456789);
'''
特例:只有整型括号里面的书架子不是表示限制位数而是显示长度
id int(8)
如果数字没有超出8位 那么默认用0填充
如果数字超出了8位 那么有几位存几位(但是还是要遵守数据的最大范围)
'''
create table t13(id int(8) unsigned zerofill);
# 用0填充至8位
# 总结:
针对整型字段 括号内无需指定宽度 因为它默认的宽度足够显示所有的数据了
浮点型
-
分类
float 、double 、decimal
-
作用
可以来存储:身高、体重、薪资
'''
存储限制
'''
float(255,30) #总共255位 小数部分最多30位
double(255,30) #总共255位 小数部分最多30位
decimal(65,30) #总共65位 小数部分最多30位
#这三者的区别就是它们的精度是不同的
# 精准度测试:
create table t15(id float(255,30));
create table t16(id double(255,30));
create table t17(id decimal(65,30));
insert into t15 values(1.111111111111111111111111111111);
insert into t16 values(1.111111111111111111111111111111);
insert into t17 values(1.111111111111111111111111111111);
# 在上面插入数据里面的时候发现float只能精确到7位,而double能精确到15位,decimal能精确30位
# 要结合实际应用场景 三者都能使用
字符类型
- 分类
'''
char
定长
char(4) 数据超过四个字符直接报错,数据不够四个字符空格补全
varchar
变长
varchar(4) 数据超过四个字符直接报错,数据不够四个有几个存几个
总结这两个的优缺点位:
char类型:
缺点:浪费空间
有点:存取都很简单
直接按照固定的字符存储数据即可
varchar类型:
优点:节省空间
缺点:存取都比较麻烦
varchar类型的存和取和网络通信中的自定义协议差不多,不过里面存储的头文件为数据的长度
建议用vachar,因为当用户数据过大的时候vachar会更省内存
'''
create table t18(name char(4));
create table t19(name varchar(4));
insert into t18 values('a');
insert into t19 values('a');
# 字符类型可以通过char_length来统计字段的长度
select char_length(name) from t18;
select char_length(name) from t19;
'''
因为mysql会自动的把你存储的数据中的空格自动剔除所以要取消mysql自动剔除字符类型里面的空格的操作
'''
# 再次修改sql_mode 让mysql 不要做自动剔除操作
set global sql_mode=
'STRICT_TRANS_TABLES,PAD_CHAR_TO_FULL_LENGTH';
date时间类型
-
分类
date:年月日 2021-5-13
datetime:年月日时分秒 2021-5-13 10:29:10
time:时分秒 10:29:10
year:年2021
create table student(
id int,
name varchar(16),
birth date,
student_time datetime
);
insert into student values('1','陈颖杰','2001-12-7',now());
enum和set枚举和集合类型
- 分类
'''
枚举(enum) 多选一
集合(set) 多选多
'''
- 具体使用
create table user(
id int,
name varchar(16),
gender enum('male','female','secrecy')
);
insert into user values(1,'陈颖杰','female');
insert into user values(2,'张程宇','女');#可以看到这个会报错,因为在枚举中只能再这里面的数据中选其中的一个
create table teacher(
id int,
name varchar(16),
gender enum('male','female','secrecy'),
hobby set('read','running','swimming','playing')
);
insert into teacher values(1,'陈颖杰','female','read'),
(2,'张程宇','female','running,playing')#在集合里面多个数据的话是通过在字符串里面的逗号来选择多个数据
;
约束条件
default 默认值
# 补充知识点 插入数据的时候可以指定字段,这个东西不写有默认字段数据
create table t1(
id int unsigned not null,#not null设置不能为空,unsigned设置无字符型
name varchar(16),
gender enum('male','female','secrecy') default 'female'
);
insert into t1(id,name) values(1,'陈颖杰');
insert into t1(gender,id,name) values('female',3,'刘昆')
unique唯一
# 单列唯一
create table t3(
id int unique,
name char(16)
);
insert into t3 values(1,'陈颖杰'),(1,'张程宇');#因为设置id字段为唯一的所以当两个id同时为1的时候这个会报错
insert into t3 values(1,'陈颖杰'),(2,'张程宇');
#联合唯一
'''
联合唯一指的是:单个数据是可以重复的,但是两个数据加起来不能完全一样
'''
create table t4(
id int,
nickname varchar(16),
unique(id,nickname), #表示id和nickname不能完全一样
name varchar(8) unique #表示名字不能重复
);
insert into t4 values(1,'小张子','张程宇'),(1,'张小子','张杰');
primary key主键
'''
单单从约束的效果来看primary key的效果等价于not null + unique,非空切唯一
'''
create table t5(id int primary key);
insert into t5 values(null);
insert into t5 values(1),(1);
#可以看到上面的结果全部错了表示主键表面上的效果真的是这两个效果的结合
create table t5(
id int primary key,
nameid int primary key);
'''
它除了有约束效果之外,它还是innodb存储引擎组织数据的依据
innodb存储引擎在创建表的时候必须要有primary key
因为它类似于书的目录,能够帮助提示查询效率并且也是建表的依据
1、一个表中有且只有一个主键,如果你没有设置主键,那么会从上往下搜索直到遇到一个非空且唯一的字段将它自动升级为主键
2、如果表中没有主键也没有其他任何的非空且唯一字段,那么innodb会采用自己内部提供的一个隐藏字段作为主键,隐藏意味着你无法使用到它,就无法提示查询速度
3、一张表中通常情况都是应该只有一个主键,并且通常将id/uid/sid字段作为主键,单字段为主键
'''
#联合主键(多个字段联合起来作为表的主键,本质还是一个主键)
create table t7(
id int,
port int,
name varchar(8),
primary key(id,port)
);
'''
创建字段的时候一定要加主键
'''
auto_increment自增
'''
当编号特别多的时候,人为的去维护太麻烦,所以就出现了自增
'''
create table t8(
id int primary key auto_increment,
name varchar(8)
);
insert into t8(name) values('陈颖杰'),('张程宇'),('刘昆傻逼');
#注意auto_increment字段只能加在key键上,不能给普通字段添加
#删除表里面的数据的时候,主键的自增不会停止,如果想重置数据就要输入
truncate t8;#清除表数据并且重置主键
外键
'''
外键就是用来帮助我们建立表和表之间的关系的
foregin key
'''
一对多关系
'''
判断表与表之间的关系,可以用换位思考的方式来判断,如:
员工表和部门表:
先站在员工表中:
思考一个员工能否对应多个部门(一条员工数据能否对应多条部门数据)
不能
再站在部门表中:
思考一个部门是否可以对应多个员工(一个数据能否对应多个员工)
可以
最后判断结果为:
一对多关系
'''
#在上面的一对多关系中,因为外键的位置在员工表中,所以先建立部门表
create table dep(
id int primary key auto_increment,
dep_name varchar(16),
dep_desc varchar(32)
);
create table emp(
id int primary key auto_increment,
name varchar(16),
gender enum('male','female') default 'male',#使用枚举类型,默认值设置为男性
dep_id int,
foreign key(dep_id) references dep(id)
);
insert into dep(dep_name,dep_desc) values('测试部','测试软件的'),('开发部','书写代码的'),('项目设计部','设计项目的'),('外交部','提项目要求的');
insert into emp(name,gender,deP_id) values('陈颖杰','male',2),('张程宇','male',1),('曾静','male',1),('小王','male',3),('小丽','female',4),('小莉','female',3),('小李','male',2),('小美','female',2);
#修改emp里面的dep_id字段
'''
先删除数据然后在重新写入
'''
#删除dep表里面的数据
'''
当删除员工表里面的数据的时候可以直接删除,但是当你想删除库的时候需要把需要删除的部门所对因的员工全部删除,才能在删除你想要删除的部门
这种删除十分的麻烦所以就出现了同步跟新和同步删除的设置:
在外键中写 on update cascade on delete cascade 表示同步跟新和同步删除出,
'''
create table dep(
id int primary key auto_increment,
dep_name varchar(16),
dep_desc varchar(32)
);
create table emp(
id int primary key auto_increment,
name varchar(16),
gender enum('male','female') default 'male',#使用枚举类型,默认值设置为男性
dep_id int,
foreign key(dep_id) references dep(id)
on update cascade
on delete cascade
);
多对多关系
'''
图书表和作者表:
站在书的角度中看一本书可以有多个作者,
站在作者的角度看一个作者可以有多本书,
所以这种关系就是多对多关系
注意:
多对多关系石创建第三张表,然后第三张表来储存图书表和作者表的关系图
'''
create table author(
id int primary key auto_increment,
name varchar(16) unique,
age tinyint,
)
create table book(
id int primary key auto_increment,
name varchar(64),
price int
)
create table book_id_author_id(
id int primary key auto_increment,
book_id int,
author_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
)
一对一关系
'''
学校的学生姓名和对应的学号:
从学号来看一个学号对应一个学生
从学生来看一个学生对应一个学号
所以这个表和表的关系为一对一关系
一对一关系就是在一对多关系中外键的地方加一个unique唯一就可以了
'''
create table student_information(
id int primary key auto_increment,
student_id int unique not null,
phone int unique
)
create table student(
id int primary key auto_increment,
name varchar(16),
student_information_id int unique,#在后面外键unique唯一那么这两个表就是一对一关系
foreign key(student_information_id) references student_infromation(id)
on update cascade
on delete cascade
)
针对表的字段名的修改
#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 新表名;
where过滤
# 作用:对整体数据的一个筛选
# 1.查询id大于等于3小于等于6的数据
select * from emp where id>=3 and id<=6; #第一种写法
select * from emp where id between 3 and 6; #第二种写法
# 2.查询薪资是20000或者18000或者17000的数据’
select * from emp where salary=20000 or salary=18000 or salary=17000;
select * from emp where salary in (20000,18000,17000);#第二种写法比上面的简洁
# 3.查询员工姓名表中含字母o的员工的姓名和薪资
'''
模糊查询
like
% 匹配任意多个字符
_ 匹配任意单个字符
'''
select name,salary from emp where name like '%o%';
# 4.查询员工姓名是由4个字符组成的 姓名和薪资
select name,salary from emp where char_length(name)=4;
select name,salary from emp where name like '____'
# 5.查询id小于3或者id大于6的数据
select * from where id not between 3 and 6;
select * from where id<3 or id>6;
# 6.查询薪资不在20000,18000,17000范围的数据
select * from emp where salary not in (20000,18000,17000);
# 7.查询岗位描述为空的员工姓名和岗位名 针对null不用等号用is
select name,post from emp where post_comment is Null;
group by分组
'''
分组实际应用场景: 分组应用场景非常的广泛
男女比例
部门的平均薪资
国家之间的数据统计
'''
# 1.按照部门分组
select * from emp group by post;
'''
分组之后 最小可操作单位应该是组,而不是组内的单个数据
上述命令在你没有设置严格模式的时候是可正常执行的 返回的是分组之后 每个组的第一条数据 但是这不符合分组的规范L:分组之后不应该考虑单个数据,而应该以组为操作单位(分组之后直接获取组内单个数据)
如果设置了严格模式 那么上面的命令会直接报错
'''
set global sql_mode = 'strict_trans_tables,only_full_group_by';#设置分组之后的数据显示格式
#设置严格模式之后 分组 默认只能拿到分组的依据
select post from emp group by post; #因为把post分组所以只能拿到post的数据
#如果要获取其他的数据需要用其他的方法
# 1.获取每个部门的最高薪资
select post,max(salary) from emp group by post;
select post as '部门',max(salary) as '最高薪资' from emp group by post;
# as 字段是给其他的数据起别名,as是可以省略的但是一般不省略方便查看
# 2.获取每个部门的最低薪资
select post,min(salary) from emp group by post;
# 3.获取每个部门的平均薪资
select post,avg(salary) from emp group by post;
# 4.获取每个部门的工资总和
select post,sum(salary) from emp group by post;
# 5.获取每个部门的人数
select post,count(id) from emp group by post;
#6.查询分组之后的部门名称和每个部门下所有的员工姓名 group_concat:获取到分组之后的普通字段的数据
select post,group_concat(name) from emp group by post;
select post,group_concat(name:'_DSB') from emp group by post;#表示在输出数据的每个name后面家一个_DSB字符
select post,group_concat(name,':',salary) from emp group by post;#输出来个数据中间用:隔开
# concat不分组的时候使用
select concat('NAME',name),concat('SAL':salary) from emp;
# 补充 as语法不单单可以给字段起别名,还可以给表起别名
select emp.id,emp.name from emp;
select id,name from emp;#这个和上面的一样
select t1.id,t1.name from emp as t1;#和上面的结果也一样,as把emp表变成了t1所以路径的数据也为t1
#7.查询每个人的年薪 不算年终奖12
select name,salary*12 from emp; #里面的数据可以直接做运算
'''
分组的注意的事项:
where和group by同时出现的时候group by在where的后面
where先对整体的数据进行过滤,然后group by在进行分组操作
聚合函数只能在分组之后使用如 max min avg
'''
having 分组之后筛选
'''
having的语法和where的语法是一致的
只不过having是在分组之后进行的过滤操作
having可以直接进行聚合函数
'''
# 1.统计各部门年龄在30岁以上的员工,平均工资保留平均工资大于10000的部门
select post,avg(salary) from emp where age>30 group by post having avg(salary) > 10000;
distinct去重
'''
一定要注意,必须是完全一样的数据才可以去重,
数据的主键的数据都是不一样的所以如果去重的时候把主键的数据带入进去的话那么数据永远不能去重成功,、
所以去重的时候一定要注意你要选择去重的字段
'''
select distinct id,age from emp;#在这个去重的案例中是带着id的因为id是主键,而主键是不重复的所以去重没有清除一条数据
select distinct age from emp; #
order by排序
select * from emp order by salary;
elect * from emp order by salary asc;#没有省略asc
#order by默认是升序 ,asc 该asc可以省略不写,也可以设置降序写法desc
select * from emp order by salary desc;
# 先按照age降序排, 如果碰到age相同 再按照salary升序排
select * from emp order by age desc,salary asc;
#统计各部门年龄在10岁以上的员工的平均工资并且保留薪资大于1000的部门,然后对平均工资降序排序
select post,avg(salary) where age>10 group by post having avg(salary) >1000 order by avg(salary) desc;
limit限制展示条数
select * from emp;
'''
针对数据过多的情况 我们通常都是做分页处理
'''
select * from emp limit 3;#表示一次性拿三条数据
select * from emp limit 0,5;#表示从第一条拿到第五条、
select * from emp limit 5,5;#表示从第六条开始往后取5条
正则
select * from emp where name regexp '^j.*(n|y)$'; #regexp表示使用正则搜索
#正则后面的算法类型的是和Python的正则格式是类似的,只是调用的方式有点不同
连表操作
select * from emp,dep;
#这种查询两个表的话,发现两种表示遍历循环的来拼接两张表
select * from emp,dep where emp.dep_id = dep.id;
#这种查询发现他们是一对一按要求的来拼接两张表
'''
MySQL中提供了连表操作的4个方法
inner join 内联(表示的是多个表之间的交集数据)
left join 左联(表示的是第一张表有第二张表没有的数据)
right join 右联(表示的是第二张表有第一张表没有的数据)
union 全联 (表示的是多张表共有的所有数据)
'''
select * from emp inner join dep on emp.dep_id = dep.id; #表示打印两个表共有的部分
select * from emp left join dep on emp.dep_id =dep.id; #表示打印两个表中emp表中的数据和所对应的数据
select * from emp right join dep on emp.dep_id = dep.id; #表示打印两个表中的dep表中和所对应的数据
#全连接的写法不一样其实就是把左连接和有连接合并只不过中间使用union来把它们联系起来
select * from emp left join dep on emp.dep_id = dep.id
union
select * from emp right join dep on emp.dep_id = dep.id;
子查询
'''
子查询就是我们平时解决问题的思路:把一个查询语句的结果当做另外一个查询语句的条件来使用(
'''
# 查询部门是技术或者人力资源的员工信息
select * from emp where emp.dep_id in
(select id from dep where name in ('人力资源','技术'));#这个是筛选出对应额部门
视图(了解)
- 什么是视图
'''
视图就是通过查询而得到的一张虚拟表 然后保存起来 下次可以直接使用
'''
- 为什么要用视图
'''
如果要频繁的操作一张虚拟表(连表查询拼表组成的等等) 你就可以制作一张虚拟表 后续可以直接操作
'''
# 视图语法
create view 表明 as 虚拟表的查询sql语句;
# 比如说讲部门表和员工表所有的信息创建一个虚拟表
create view emp_dep_all as
select emp.id,emp.name as emp_name,sex,age,dep.name as dep_name from emp right join dep on emp.dep_id = dep.id
union
select emp.id,emp.name as emp_name,sex,age,dep.name as dep_name from emp left join dep on emp.dep_id = dep.id;
#在上面注意事情就是创建视图的时候要避免数据的字段名相同,如果数据的字段名相同那么数据就会出现问题
'''
视图其实就是一张表只不过在创建表的时候是没有约束条件,只有数据
视图是的存储是只有表结构文件,没有表数据文件,视图表的数据还是来自于原来中的表的数据
视图一般只用于查询里面的数据,不用来修改,因为修改了之后可能会影响原来的表数据,所以一般来说是不能修改视图里面的数据
,因为视图里面的数据是来自之前的数据所以可以通过修改原来的表的数据来修改视图里面的数据
'''
触发器(了解)
在满足在对表数据增删改的情况下 自动触发功能
触发器可以帮助我们实现监控、日志…
触发器可以在六中情况下自动触发。增前增后 改前改后
- 触发器的语法结构
create trigger 触发器的名字 before/after insert/update/delete on 针对的表的名字
for each row
begin
sql语句
end
# 具体使用 针对触发器的名字 我们通常需要做到见名如意
# 针对增加数据之后触发的效果
#注意在调用的之前和之后要修改结束符,不然在创建语句的时候就会出现报错
delimiter &&
create trigger experiment_inshow_after after insert on experiment
for each row
begin
insert into experiment_intime(insert_time) values(now());
end &&
delimiter ;
# 删除指定的触发器
drop trigger 触发器名字;
#mysql个人制作添加数据日志
create table experiment(
id int primary key auto_increment,
name varchar(20) not null,
gender enum('male','female','secrecy') not null,
modify_time datetime not null default now()
);
create table experiment_intime(
id int primary key auto_increment,
insert_time datetime not null,
);
delimiter &&
create trigger experiment_inshow_after after insert on experiment
for each row
begin
insert into experiment_intime(insert_time) values(now());
end &&
delimiter ;
insert into expriment(name,gender) values
('陈颖杰','female'),('张程宇','female');
事物(需要掌握)
-
什么是事物
开启一个事务可以包含多条sql语句,这些sql语句要么同时成功,要么一条都别想成功 这个称之为事物的原子性
-
事物的作用
保证了对数据操作的安全性
-
事物的四大特性
-
原子性
一个事物是一个不可分割的单位,事物中包含的诸多操作要么同时成功要么同时失败
-
一致性
事物必须是使数据库从一个一致性的状态变到另外一个一致性的状态一致性和原子性密切相关
-
隔离性
一个事物的执行不能被其他事物干扰(即一个事物内部的操作及使用到的数据对并发的其他事物是隔离的,并发执行的事物之间也是互不干扰的)
-
持久性
一个事物一旦提交成功执行成功那么它对数据库中的修改应该是永久的接下来的其他操作或者故障不应该对其有任何影响
-
-
如何使用事物
# 事物相关的关键字 # 1 开启事物 start transaction; # 2 回滚(回到事物执行之前的状态) rollback; # 3 确认(确认之后就无法回滚了) commit; # 事物一般作用于修改表的操作,如果只是想查询表的数据就不需要使用到事物
存储过程
储存过程就类似于python中的自定义函数
它的内部包含了一系列可以进行执行的sql语句,存储过程存放于MySQL服务端中,你可以直接通过调用存储过程触发内部sql语句的执行
基本使用
create procedure 储存过程的名字(参数1,参数2) #括号里面可以传递参数
begin
sql 代码
end
#调用
call 存储过程的名字();
#案例
delimiter &&
create procedure showta()
begin
show tables;
end&&
delimiter ;
# 定义变量
set @ret = 10;
# 查看变量对应的值
select @ret;
#删除存储过程
drop procedure 储存过程的名字;
函数
和存储过程是由区别的,存储过程是自定义函数,还这里面的函数是mysql里面自带的内置函数
now() # 表示当前的时间
max() # 计算里面的最大数据
min() # 计算里面最小的数据
avg() # 计算里面的平均数
#其他的看mysql官方
索引
数据都是存在与硬盘上的,查询数据不可避免的需要进行io操作
索引就是一种数据结构,类似于书的目录。意味着以后在查询数据的应该先找目录再找数据,而不是一页一页的翻书,从而提升查询速度降低io操作索引在MySQL中也叫“键”,是存储引擎用于快速查找记录的一种数据结构
- primary key
- unique key
- index key
注意foreign key不是用来加速查询用的,不在我们的而研究范围之内上面的三种key,前面两种除了可以增加查询速度之外各自还具有约束条件,而是最会一种index key没有任何的约束条件,只是用来帮助你快速查询数据
- 本质:
通过不断的缩小想要的数据范围筛选出最终的结果,同时将随机事件(一页一页的翻)变成顺序事件(先找目录,再找数据)也就是说有了索引机制,我们可以总是用一种固定方式查找数据
一张表中可以有多个索引(相当于多个目录)
-
缺点
- 当表中有大量数据存在的前提下,创建索引速度会非常的慢
- 在索引创建完毕之后,对表的查询的性能会大幅度提升,但是对写的性能会大幅度的降低
-
总结
索引不要随便的创建
聚集索引(primary key)
'''
聚集索引指的就是主键
innodb 只有两个文件 直接将主键存放在idb表中
myisam 三个文件 单独将索引存在一个文件中
'''
辅助索引(unique,index)
查询数据的时候不能一直使用到主键,也有可能会用到name,password等其他字段那么这个时候你是没有办法利用聚集索引。这个时候你就可以根据情况给其他字段设置辅助索引(也是一个b+数)
'''
叶子的节点存放的是数据对应的主键值
先按照辅助索引拿到数据的主键值
之后还是需要去主键的聚集索引里面查询数据
'''
覆盖索引和非覆盖索引
在辅助索引的叶子节点就已经拿到了想要的数据
# 给name设置辅助索引
select name from user where name = '刘昆'
#在name表中查找name里面的数据那么就不需要通过聚集索引来查找,可以直接的在name表中查找,这种情况就是覆盖索引
select * from user where name = '刘昆'
#这种不能直接的通过name表中来进行查询数据的必须装换为索引来进行二次查询的这种就是非覆盖索引
MySQL主要存储引擎
- Innodb
- 是MySQL5.5及版本之后默认的存储引擎
- 存储数据更加的安全
- myisam
- 是MySQL5.5版本之的默认存储引擎
- 速度要比Innodb更快,但是安全性没Innodb高
- memory
- 内存引擎(数据全部存储在内存中)断电数据流失
- BlackHole
- 无论存什么,都会立刻消失(黑洞)
#查看所有的存储引擎语法:
show engines;
#不同的储存引擎在储存表的时候 异同点
create table t1(id int) engine=innodb; #这个创建的表具有表结构文件和表数据文件
create table t2(id int) engine=myisam; #这个创建的表具有表结构文件和表数据文件和表索引文件(索引文件是方便数据查找的,加快数据查找速度)
create table t3(id int) engine=memory; #只有表结构
create table t4(id int) engine=blackhole;#只有表结构
#存数据
insert into t1 values(1);
insert into t2 values(1);
insert into t3 values(1);
insert into t4 values(1);
#查看各个表里面的数据情况
select * from t1;
select * from t2;
select * from t3;
select * from t4;
#在存数据之后直接查询可以看到t1、t2和t3都有数据,但是重启服务器之后只有t1和t2有数据,这个也可以证明t3表数据是在内存里面的存储的