MySQL是最流行的关系型数据库
先明确两个概念
- 数据库的定义:数据库是“按照数据结构来组织、存储和管理数据的仓库”。是一个长期存储在计算机内的、有组织的、可共享的、统一管理的大量数据的集合。俗称
Database(DB)
- 数据库管理软件:对数据库进行管理和控制,包括了增删查改等操作,使用和维护数据库。俗称
DataBase Management System(DBMS)
安装配置启动MySQL
可能是Windows,Mac,Linux,Dokcer
等安装方式,网上的安装教程很多
为了快速启动学习,演示Docker
进行安装(Docker
本体安装自行搜索),安装后可以使用Navicat Premiun,SQLyog
之流的图形化工具去管理使用,出于学习目的,这里只使用命令行
docker run --name testDbContainer -v ~/testDb:/root -e MYSQL_ROOT_PASSWORD=12345678 -e MYSQL_DATABASE=testDb -p 3306:3306 -d mysql:8.0.29-oracle
这段命令的作用是启动一个MySQL
的容器,如果当前没有对应镜像会先下载,然后启动并输出容器ID
,3306
是MySQL
默认端口
--name [customName]
指定了容器名字-e MYSQL_ROOT_PASSWORD=[password]
指定了root
用户的密码-e MYSQL_DATABASE=[testDb]
创建一个名为testDb
的数据库-p 3306:3306
指定了宿主机(冒号前)与容器(冒号后)之间的端口映射,可以理解为访问启动Docker
的机子(就是我们使用的机子,宿主机)的3306
端口,就是访问容器里的3306
端口,容器可以理解为一台完整的主机,可以选择自己想使用的端口号-d
表示在后台运行,mysql:8.0.29-oracle
指定了镜像名及版本(此版本M1可用)docker ps -a
可以查看所有Docker
的容器列表,包括没有运行的容器
docker exec -it [容器Id/容器名称] /bin/bash
这段命令中exec
是execute
的缩写(执行)。-i
是交互模式。-t
是分配终端。docker
的options
可以连起来缩写(-it
)。目标容器可以用id或者名称指定,id不一定要输全,输入到保证没有其他容器id重复即可。-v 宿主机路径:容器路径
指定了数据卷的映射,简单理解为我当前本机的目录就是容器主机里的对应目录,访问容器内的目录等同于访问宿主机。/bin/bash
指要运行的命令。总结就是通过exec
命令对指定的容器执行脚本命令并提供一个可交互的终端,在bash
中输入exit
可以退出终端交互mysql -uroot -p12345678
在终端中输入命令,通过账号密码登陆mysql
,出现下图所示输出就配置环境完毕,可以开始MySQL
的学习之旅了
开始入门
主要学习的是SQL
语句 -- 结构化查询语言(Structured Query Language
)
这里要捋清楚数据库-数据库管理系统-SQL
语言三者的关系
- 数据库是存放数据的地方,一个文件(特定结构)就可以看成一个数据库
- 数据库管理系统是专门用来管理数据库的软件,可以增删查改(
CRUD
)操作数据库 SQL
编写后通过DBMS
编译执行来达到操作数据库的目的CRUD
补充
C增(Create
)R查(Retrieve
,不是Read
)U更新(Update
)D删除(Delete
)
SQL的分类
- 数据库查询语言 DQL(Data Query Language)
select
- 数据库操纵语言 MDL(Data Manipulation Language)
insert,delete,update
- 数据库定义语言 DDL(Data Definition Language)
create,drop,alert
- 事务控制语言 TCL Transactional Control Language)
commit,rollback
- 数据控制语言 DCL(Data Control Language)
grant,revoke
查看使用的数据库版本
select version();
查看当前所有数据库
show database;
(SQL语句遇分号才执行,且不分大小写)会自带4个默认的数据库,下图名为demo
的数据库就是通过docker
命令启动时创建的
使用数据库
use [数据库名];
执行后会提示当前使用数据库已发生改变
select database();
查看当前使用的数据库
创建数据库
create database [数据库名];
执行后会输出执行状态,下图表示创建成功
查看当前数据库所有的表
show tables;
当前还没有任何表,执行后只会输出Empty set (0.00 sec)
创建表及插入数据
在这之前需要先认识MySQL中的数据类型
比较常见的类型 | 类型描述 |
---|---|
char (255) | 定长字符,不管实际存储值是多少,分配的存储空间大小都是给定的字符长度空间,示例表示最多存储255个字符,速度快 |
varchar (255) | 可变长度字符,会动态的根据实际存储数据分配存储空间,示例表示最多存储255个字符,速度稍慢,因为动态分配计算过程需要时间 |
int | 最长11位,数字整数类型,等同于Java中的int,int(3)表示最大存储三位数📄 |
text | 长文本数据 |
bigint | 等同于Java中的long |
float | 等同于Java中的float |
double | 等同于Java中的double |
date | 短日期类型,只有年月日 |
datetime | 长日期类型,包含年月日时分秒毫秒 |
clob | 字符大对象,最多可以存储4G的字符串,clob是Character Large Object的缩写 |
blob | 二进制大对象,用于存流媒体数据,插入时要使用IO流,blob是Binary Large Object的缩写 |
类型列表并不全,其他不常用的可以有需要用到时再查看,这里只做一个简单认识
创建语法格式为create table [表名] (字段名 数据类型 [可选列约束], ...以此排列)
;
CREATE TABLE t_user (
id INT PRIMARY KEY auto_increment,
username VARCHAR ( 10 ) UNIQUE
);
上述语句表示创建一个名为t_user
的表,其中有两个字段,一个叫id
到为int
类型,作为该表的主键(非空且不能重复,后面约束会讲),id
的值自增1
。username
字段则为可变长度字符,最多10
个字符且不能有重名。
此时再执行show tables
就能看见表名的输出
查看表结构,创建后,可以通过desc [表名]
查看表的结构(不是表数据),分别列出了每个字段的结构配置
在字段名后加上
default
跟上值,表示username
字段当没有传值时,默认会使用配置的default
值填充,sql
中的字符串用单引号
包裹,效果不演示了
create table t_user (
id int primary key auto_increment,
username varchar ( 10 ) default 'test'
);
insert 插入语法
语法结构为insert into [表名] (字段名) values(按顺序对应字段的值);
- 这里有两个要点,第一:字段名可以忽略,但忽略后,需要把所有的字段都一一填写在
values
中,示例insert into t_user values(1,'JackMa');
- 第二:被自增约束的字段可以不传入,
values
后面可以一次插入多行数据,只需要用逗号进行隔开,用小括号包裹另一行的值,示例insert into t_user(username) values('aaa'),('bbb'),('ccc');
这段语句表示向
t_user
表插入三条数据
这里列举一些使用特性
字段类型/函数/规则 | 说明/特性 |
---|---|
mysql的日期格式 | %Y=年,%m=月,%d=日,%h=时,%i=分,%s=秒 注意大小写 |
now() | 获取当前系统时间 |
date_format(字段,格式) | 可以将日期转换成特定格式,如查询时可以将日期字段使用函数进行特定格式处理! |
str_to_date(日期字符串,格式) | 当插入时如果日期符合%Y-%m-%d(2000-01-01) 格式,则可以不需要使用str_to_date 函数,等价于这样写insert into t_user (username, age, gender,created_at) values('J12fs', 15, 1,str_to_date('2020-01-21','%Y-%m-%d')); |
date,datetime | insert时可以使用now()函数,date会取当天,datetime会取当前年月日时分秒,使用示例insert into t_user (username, age, gender,created_at) values('J13fs', 15, 1, now()); |
update 更新/修改语法
语法结构为update [表名] set 字段名 = 值,字段名 = 值 where 条件
条件语句不加会导致整张表进行更新,使用时一定要加上条件,如where id = 1
才进行更新
这段语句表示将性别是男的数据都设置年龄为30岁
delete 删除数据
语法结构为delete from [表名] where 条件
条件语句不加会导致整张表进行删除,使用时一定要加上条件,如where id = 1
才进行删除
这段语句表示将所有
id=2
的数据进行删除
drop 删除表
drop table [表名]
执行后整张表包括数据都会被删除,可以加上一个判断条件,drop table if exists t_user;
,加入了if exists
关键字,表名只有表存在情况下才会进行删除表操作,没有表时执行删除会报错
truncate 大表删除
使用delete
语句进行删除效率比较慢,数据空间不会释放,数据可以被回滚,硬盘上的真是存储空间仍然被占用
当确定数据确实不再有使用价值时,可以使用truncate
进行删除
- 对比
delete
,这是物理删除空间会被释放,效率更高效truncate [表名];
请谨慎操作
alter 修改表结构
尽量做到设计表时就处理好表结构,这里8说了
select 查询数据(DQL重中之重)
在查询前,需要有数据进行查询,所以先执行下面这段SQL
语句,先堆数据
drop table if exists t_user;
create table t_user (
id int primary key auto_increment,
username varchar(10) unique,
age int(3),
gender int(1) comment '1表示男,0表示女'
);
insert into t_user (username, age, gender) values('Jack', 15, 1),('Mike', 20, 1),('Susan', 22, 0);
插入数据有两种方式
- 一种是手动的执行每一行sql(直接复制粘贴也会自动执行)
- 使用读取
SQL
文件的方式,将上面SQL
保存到sql
后缀的文件文件当中,使用source [文件地址];
的方式进行批量导入,由于使用了Docker
,并且进行了数据卷映射-v ~/testDb:/root
,这样容器内也可以读取宿主机的本地文件,所以按照我的配置,只要把文件保存到宿主机的~/testDb
目录下,再在容器中的bash
执行source /root/testDb.sql
就能批量执行sql
文件中的语句
说了导入顺便讲讲导出
SQL
的命令,先exit
退出mysql
回到bash
中,输入以下命令
mysqldump [数据库名称] > [目标文件地址] -uroot -p12345678
,提示是说明文密码不安全可以忽略,由于我进行了容器的数据卷映射,所以可以去宿主机查看导出文件
查看被映射的宿主真机对应的文件夹,对应的文件便有了
select语句
最基本的查询语法格式select 1个或多个字段名 from [表名]
,可以使用*
通配符,表示查询所有字段,执行时会被解析成id,username,age,gender
。select和from是关键字,字段名和表名是标识符,查询多个字段用逗号隔开,为了演示使用了*
,实际中不建议使用,可读性差,效率相对低
给字段设置别名
查询时将字段转成其他名字进行查看,as
关键字可以省略,字段名与别名使用空格隔开即可
字段名可以进行数学计算
表达式会设置为默认别名,对应的列数据也进行了数学运算
条件查询
select (一个或多个字段名) from [表名] where (一个或多个条件);
操作符 | 操作符描述 |
---|---|
= | 等于,select * from t_user where id = 1; 查询id等于1的数据 |
!=,<> | 不等于,两种写法等价,select * from t_user where id <> 1; 查询id不等于1的数据 |
< | 小于,select * from t_user where id < 2; 查询id小于2的数据 |
= | 等于,select * from t_user where id > 1; 查询id大于1的数据 |
>= | 大于等于,select * from t_user where id >= 2; 查询id大于等于2的数据 |
<= | 小于等于,select * from t_user where id <= 1; 查询id小于等于1的数据 |
between ... and ... | 等价于 x >= 1 and x <= 2 的写法,需要遵循左小右大 select * from t_user where id between 1 and 2; 等规则,否则会报错,查询id>=1且id<=2的数据 |
and | 并且,只有and左右两边的表达式都成立才算复合条件 select * from t_user where id = 1 and age > 10; 查询id等于1且年龄大于10的数据 |
or | 或者,or任意一边的表达式成立都算复合条件 select * from t_user where id = 1 and age > 10; 查询id等于1或者年龄大于10的数据 |
in | 包含,可以替换or实现同等查询效果 select * from t_user where username in ('Jack', 'Mike'); 查询usernmae等于Jack或者等于Mike的数据 |
like | 模糊查询,支持%或者_下划线,百分号表示匹配任意个字符,下划线表示匹配一个字符,想匹配的字符中就有下滑线时,需要使用\_ 进行转义, select * from t_user where username like '%c\_k%'; 查询usernmae包含c_k的数据,c_k的前面或者后面有没有字符都可以 |
排序
select * from t_user order by 字段名 排序方式,字段名 排序方式
排序可选的值有asc
和desc
,不写排序方式默认为升序(等于同写了asc
)
多个字段排序只需要用逗号进行分割,规则为只有前面的排序结果为相等时,才会采用后面的排序条件,如
order by age asc,id desc
,age
相等的话就会使用id
进行排序
还可以根据查询字段的序号进行排序,默认从1开始,order by后的字段名用序号替代,可读性差且依赖字段,不建议使用
数据处理函数
又被称为单行处理函数,一个输入对应一个输出,一些常用的函数列举,可以用在select
后的字段,也可以用在where条件
后的字段
函数 | 语法作用 |
---|---|
lower | 将目标字段数据转为小写 select lower(username) from t_user; |
upper | 将目标字段数据转为大写 select lower(username) from t_user; |
substr | 将username是J开头的数据查出,可以做到和like相同的功能 select * from t_user where substr(username,1,1) = 'J'; 语法:substr(字段名,字符索引1开始,截取多少个不写的则相当于截剩余部分) |
concat | 字符串拼接,将username字段的查询结果转为小写开头,结合了substr和lower select concat(lower(substr(username,1,1)),substr(username,2)) result from t_user; 语法格式:concat(字符,字符,...字符) |
length | 取字符长度 select length(username) len from t_user; |
trim | 如果字符前后有空格则去掉 select trim(username) len from t_user; |
round | 四舍五入(支持正负数),将查出数据的年龄进行个位数的四舍五入 select round(age,-1) from t_user; |
rand | 生成随机数,生成0-100的随机数,套了层round进行四舍五入 select round(rand() * 100) from t_user; |
ifnull | 空值处理,需要注意在所有数据库中,涉及和null进行数学运算的结果都是null,当年龄为空时将结果集的值设为100,不会修改源数据 select ifnull(age,100) from t_user; |
case...when...then...else...end | sql中的switch case语句,如果年龄为20的则年龄乘以2,否则原值输出 select case age when 20 then age*2 else age end as result from t_user; |
分组函数
又称为多行处理函数,输入多行最终输出一行,与单行处理函数相反
group by 分组
将表按照一个字段或多个字段进行分组group [字段1,字段2...]
,
在使用分组函数前需要先对表进行group by
分组,当没有写group by
时默认整张表为一组,分组函数也不能写在where
关键字后面,因为涉及到执行顺序问题
select sum(age) result,gender from t_user where id > 1 group by gender order by result desc;
这段SQL
的执行顺序为,先1 from
,2 where
,3 group by
,4 select
,5 order by
,当执行到where
时此时表还没有进行分组,所以不能将分组函数应用到where
条件中,这段SQL
会先将id>1的筛选掉,然后进行性别分组查询,分组后将组里的年龄求和最后按照求和的结果降序排列
- 如果有
group by
语句,则select
后面跟随的只能是被排序的字段和分组函数 - 联合字段使用逗号进行隔开即可,会将两个字段合并起来当成一个字段进行分组
having 过滤
having
需要配合group by
,无法单独使用,可以对分组后的数据进行筛选,having
的执行时机在group by
之后,select
之前
select sum(age) result,gender from t_user where id > 1 group by gender having result > 50 order by result desc;
直接在上面的示例加一句having result > 50
,则数据会将年龄综合低于50的筛选掉
distinct
将查询结果相同的去重,distinct
关键字只能出现在selec
之后字段之前
select distinct age from t_user;
这段代码会将年龄相同的数据从结果集中筛选掉,如果有多个字段就表示联合去重(多字段联合起来相同才会去重)
第一篇先🚪到这 : )