MySQL基础笔记

本篇文章为我个人MySQL基础知识复习笔记,记录的比较粗略,旨在自己能看懂,所以各位读者如果恰好看到本篇笔记并阅读,遇到不详细的地方还是需要自己查更详细的资料,见谅!!!

测试数据请见文章末尾

1、DQL 数据查询语言(data query language)

1.1 函数

# 字符函数
## length(字符长度)
select length('Hello World!'); # 12
## concat(拼接文本),
select concat('Hello', ' ', 'World', '!'); # Hello World!
## upper、lower 字母大小写转换
select upper('Hello World!'), lower('Hello World!'); # HELLO WORLD!, hello world!
## substr/substring(字符串截取,索引位置从1开始计算)
select substr('0123', 2), substr('0123', 2, 1); # 123, 1
## instr(返回substr在str中第一次出现的索引位置,若不匹配返回0,索引从0开始)
select instr('0123', '1'), instr('0123', 4); # 2, 0# trim(去除收尾空格,字符串中间空格不会去除)
select trim(' Hello World! '), length(trim(' Hello World! ')); # Hello World!, 12
## lpad(长度不够指定长度左边填充自定字符,长度超出指定长度去掉字符末尾部分)
select lpad('Hello World!', 14, '*'); # **Hello World!
## rpad(字符右边填充)
select rpad('Hello World!', 14, '*'); # Hello World!**
## replace(替换指定字符)
select replace('Hello World!', '!', '?'); # Hello World?

# 数学函数
## round(四舍五入)
select round(3.1415), round(3.1415, 2); # 3, 3.14
## cell(向上取整)、floor(向下取整)
select ceil(3.14), floor(3.14); # 4, 3
## mod(取余)
select mod(10, 3), 10%3; # 1, 1

# 日期函数
## now()、current_timestamp(获取当前日期及时间)
select now(), current_timestamp; # 2022-01-08 18:58:41, 2022-01-08 18:58:41
## curdate()、current_date(获取当前日期)
select curdate(), current_date; # 2022-01-08, 2022-01-08
## curtime()、current_time(获取当前时间)
select curtime(), current_time; # 18:58:41,18:58:41
## year、month、date、hour、minute、second(提取指定时间字符串里面的年月日)
select year(now()), year('2020-01-08'); # 2022, 2022
## str_to_date(指定格式字符串转换成时间,%Y:2022、%y:22、%m:01、%c:1、%d:08...)
select str_to_date('2020年01月08日', '%Y年%m月%d日'); # 2020-01-08
## date_format(时间转换成指定格式的字符串,%Y:2022、%y:22、%m:01、%c:1、%d:08...)
select date_format(now(), '%Y年%m(%c)月%d日 %H(%h):'); # 2022年01(1)月08日 19(07):
## datediff(求两个日期间隔,前者-后者,只能精确到天)
select datediff(now(), '2021-01-08');

# 统计函数
## sum(求和)、avg(求平均值),只能处理数值类型
select sum(age), avg(age) from student;
## max、min、count(*代表某行只要有一列不为空就算,指定列名的话就统计指定列,空则不算)
select max(age), min(age), count(*) from student;

# 流程控制函数
## if(条件判断)
select if(1=1, 'yes', 'no'), if(1=2, 'yes', 'no'); # yes, no
## ifnull(判断是否为null)
select ifnull('Hello World!', 'is null'), ifnull(null, 'is null'); # Hello World!, is null

# 其他函数
## version(数据库版本)、database(当前数据库)、user(当前连接用户)、password(指定用户密码)
select version(), database(), user(), password('root'); # 5.7.24、test、[email protected]、81F...

# 附加其他
## 取别名,可以用as,也可以用空格
select  name as 姓名, age 年龄 from student;
## 去重(distinct)
select distinct age from student;

1.2 查询

# 条件查询
  # 语法:select 查询列/统计函数 from 表名 where 条件
  # 条件表达 <、>、=、!=/<>、<=、>=、 is [not] null
  # 逻辑表达 &&或and、||或or、!或not
  # 模糊查询
    # like(%匹配任意多个字符、_匹配一个字符)
    # between and(左闭右闭)
    # in(不支持通配符,例如 % 、_ ...)
select * from student where classId=1 or classId=2;

# 分组查询
  # 语法:
  #      select 统计分组字段, 统计函数 
  #      from 表名 [where 条件] 
  #      group by 字段 
  #      [having 包含统计函数的字段]
select classId, count(*) count from student group by classId having count>1;

# 查询结果排序
  # 语法:
  #      select 查询列/统计函数 
  #      from 表名 [where 条件] 
  #      [group by 字段 having 包含统计函数的字段] 
  #      order by 字段 asc/desc
select * from student order by age desc;

# 分页查询
  # 语法:
  #      select 查询列/统计函数 
  #      from 表名 
  #      [group by 字段 having 包含统计函数的字段] 
  #      [order by 字段 asc/desc] 
  #      limit [pos,] size
  # 注意:pos索引从0开始,可选,不写默认是从0开始,计算公式 limit (page-1)*size, size
select * from  student limit 2;
select * from  student limit 0,2;

# 多表连接查询
## 内连接(不加连接条件会产生笛卡尔效应,加连接条件会查询两张表的**交集**)
### 92版等值连接,语法:select ... from 表1, 表2, ... where 条件 ...
select s.*, c.* from student s, class c where s.classId=c.id;
### 99版等值连接,语法:select from 表1 [inner] join 表2 on 连接条件 ...
select s.*, c.* from student s join class c on s.classId=c.id;
### 非等值连接
#### 查询所有学生分数所属等级
select s.name, s.grade, gl.level from student s 
    join grade_level gl 
        on s.grade between gl.l_grade and gl.h_grade;
### 自连接(连接自己)

## 外连接(分主表和从表,left左边为主表,right右边为主表,不加where条件会查询出主表的全部内容)
### 左外连接,语法:select from 主表名 left [outer] join 从表名 on 连接条件 ...
#### 查询所有学生及所在班级
select s.id, s.name, s.classId, c.name from student s 
    left join class c on s.classId=c.id; 
#### 查询没有(没合理)分配班级的学生
select s.id, s.name, s.classId, c.name from student s 
    left join class c on s.classId=c.id where c.id is null;
#### 查询合理分配了班级的学生
select s.id, s.name, s.classId, c.name from student s 
    left join class c on s.classId=c.id where c.id is not null;
### 右外连接,语法:select from 从表名 right [outer] join 主表名 on 连接条件 ...
#### 查询所有学生及所在班级
select s.id, s.name, s.classId, c.name from class c 
    right join student s on s.classId=c.id;

# 子查询
  # 子查询位置可以放在select、from及where或having后面
## select 后面,仅支持标量子查询(一行一列)
#### 查询每个班学生个数
select c.*, 
       (select count(*) from student s where s.classId=c.id) scount 
from class c;
## from 后面,支持表子查询(多行多列),注意:from后面的表子查询,必须起别名
#### 查询每个班级平均成绩水平
select t.classId, t.avg_grade, g.level 
from (select s.classId classId, avg(s.grade) avg_grade 
      from student s 
      group by s.classId) t 
    left join grade_level g 
      on t.avg_grade between g.l_grade and g.h_grade; 
## where/having 后面 支持标量子查询(一行一列)、列子查询(多行一列)、行子查询(一行多列)
### 标量子查询(一行一列)
#### 查询成绩比Anne好的
select * from student where grade>(select grade from student where name='Anne');
### 列子查询(多行一列)
#### 查看Bob老师所带班级的全部学生
select * from student where classId in (select c.id from class c where teacher='Bob');
### 行子查询(一行多列)
#### 查询年级最小且成绩最差的学生信息,有则输出(注:有偶然性,年级小的成绩不一定是最差)
select * from student where (age, grade)=(select min(age), min(grade) from student);

# 联合查询
  # 语法:查询语句1 union [all] 查询语句2
  # 特点:查询列数一致;每个查询语句的列的排序一致;union会去重,显示全部需要加上all
select id, name from student union select id, name from class;
select id from student union select id from class; # sql会自动去重
select id from student union all select id from class; # 查询全部数据,不去重

2、DML 语言(data manipulate language)

# 插入
## 方式一:insert into 表名 (列名...) values (值...) ...
insert into class (name, teacher) values ('五班', 'John');
insert into class (name, teacher) values ('六班', 'Bob'), ('七班', 'Bob');
## 方式二:insert into 表名 set 列名=值... ...
insert into class set name='八班', teacher='Bob';
## 支持子查询的方式插入
insert into class select 10, '十班', 'Bob';
insert into class select 11, '十一班', 'Bob' union all select 12, '十二班', 'Bob'

# 更新
  # 语法:update 表名 set 列名=值... where ....
## 单表记录修改
update class set teacher='John' where id=4;
## 多表记录修改
#### 例如将未合理分配班级的学生分配到4班
update student s 
    left join class c on s.classId=c.id 
set s.classId=4 where c.id is null;

# 删除
## delete 单表删除
delete from class where id = 10;
## delete 配合limit使用,限制删除条数
delete from class where id > 9 limit 1;
## delete 连表删除
#### 删除那些还没有分配学生的班级
delete c from class c left join student s on c.id=s.classId where s.id is null;
## delete 多表删除
#### 删除John老师所带班级,并且和所在班级的全部学生
delete c,s from class c join student s on c.id=s.classId where c.teacher='John';
## truncate 删除指定表里面所有记录,并重置索引,效率比delete高
truncate table class;
delete from class;

3、DDL 数据定义语言(data definition language)

3.1 库和表的管理

# 库管理
## 查看所有数据库
show databases;
## 库创建,if not exists 为可选
create database if not exists books;
## 指定使用的数据库,语法:use 库名
use books;
#### 库删除,if exists 为可选
drop database if exists books;

# 表管理
## 查看该数据库下的所有表
show tables;
## 表创建,语法:create table [if not exists book] 表名 (字段 类型 [长度, 约束], 字段 类型 [长度, 约束] ...)
create table if not exists book (id int, name varchar(20), author varchar(20));
## 表信息展示,语法:describe 表名
describe book;
## 修改类型和约束,语法:alter table book modify [column] 列名 新类型
alter table book modify name varchar(21);
## 修改列名或列名和类型同时修改,语法:alter table 表名 change [column] 旧名 新名 旧类型/新类型
alter table book change name book_name varchar(20);
## 添加新列,语法:alter table 表名 add [column] 字段 类型 [约束] [first/after 已有字段];
alter table book add price float;
alter table book add price float after id; # 新列放在id列后面
alter table book add price float first; # 新列放在最前面
## 删除列,语法:alter table 表名 drop [column] 列名
alter table book drop price;
## 修改表名,语法:alter table 表名 rename 新表名
alter table book rename books;
## 表复制,只复制结构,语法:create table 新表名 like 表名/库名.表名
create table class_copy like class;
#### 表复制,结构加数据,语法:create table 新表名 select * from 旧表名
create table class_copy2 select * from class;
#### 复制表,结构加部分数据,语法:create table 新表 select * from 旧表名 where ...
create table class_copy3 select * from class where id<2;
#### 复制表,部分结构加数据,语法:create table 新表 select 需要复制的列名... from 旧表 where ...
create table class_copy4 select id, name from class;
#### 表删除,语法:drop table [if exists] 表名
drop table if exists book;

3.2 常见列类型

# 常见数值类型
## 数值型,超过则填充临界值
  # 类型                大小          注意
  # tinyint           1 byte
  # mediumint         2 byte
  # int/integer       4 byte
  # bigint            8 byte
  # float             4 byte
  # double            8 byte
  # decimal(m,d)      依赖m和d的值    如果m>d,为m+2否则为d+2
## 字符型
  # 类型                大小              n取值(字符个数)                   注意
  # char(n)           0-255 byte        0-255,可省略,省略默认为1       固定长度字符串,不够后面补空格,取出会去掉尾部空格
  # varchar(n)        0-65535 byte      字符转换成二进制不能超过65535     可变长度字符串
  # text              0-65535 byte                                    长文本数据
  # blob              0-65535 byte                                    二进制形式的长文本数据
## 日期型
  # 类型                大小      范围                                      注意
  # date              3 byte  [1000-01-01, 9999-12-31]
  # time              3 byte  [-838:59:59, 838:59:59]
  # year              1 byte  [1901, 2155]
  # datetime          8 byte  [1000-01-01 00:00:00, 9999-12-31 23:59:59]  不会根据机器时区变化
  # timestamp         4 byte  [1970-01-01 00:00:00, 2038-xx-xx xx:xx:xx]  存储的是格林威治时间,取出时会根据系统时间进行格式化

3.3 常见约束&标识列

# 常见约束
## not null(不能为空),仅支持列级约束
create table if not exists book (id int not null);
## default(指定默认值),仅支持列级约束
create table if not exists book (id int default 0);

## unique(唯一键,用于保证字段唯一,字段可以为null),支持列级约束和表级约束(constraint 和别名可以省略)
create table if not exists book (id int unique);
# create table if not exists book (id int, constraint id unique(id)); # 不推荐使用表级约束
# create table if not exists book (id int, unique(id)); # 不推荐使用表级约束

## primary key(主键,非空和唯一的合集,但是只能指定一个字段为主键),支持列级约束和表级约束(constraint 和别名可以省略)
create table if not exists book (id int primary key);
#### 单个主键,使用表级约束(不是很规范)
# create table if not exists book (id int, primary key(id)); 
#### 复合主键,必须使用表级约束
create table if not exists book (id int, 
                                 name varchar(20), 
                                 auth_id int, 
                                 constraint book_pk primary key(name, auth_id));

## foreign key(外键),仅支持表级约束,语法:... [constraint 别名] foreign key(本表字段) references 外表(关联的外表中的字段)
create table if not exists book (id int primary key, authId int,
                                constraint fk_book_student foreign key(authId) references student(id));
create table if not exists book (id int primary key , authId int,
                                foreign key(authId) references person(id));

## 列级约束修改,语法:alter table 表名 modify [column] 列名 类型 [新约束]
alter table book modify column id int unique;

# 标识列
  # auto_increment(自增长),只能用来标识数值类型列
create table if not exists book (id int primary key auto_increment);
## 添加标识列
alter table book modify id int auto_increment;
## 删除标识列
alter table book modify id int;

4、TCL 事务(transaction control language)

# 特征:ACID
  # atomicity(原子性)
  # consistency(一致性)
  # isolation(隔离性)
  # durability(持久性)
# 分类
  # 隐式事务 insert、update、delete
  # 显示事务,实现步骤如下
    # 1、set autocommit=0; 针对本次会话
    # 2、start transaction; 可选
    # 3、sql 语句
    # 4、savepoint point; 可选,自己设置的回滚节点名
    # 5、sql 语句
    # 6、rollback to point; 可选,有需要回滚的节点可以加上
    # 4、commit/rollback;
# 事务级别(mysql默认事务级别 repeatable read)
  # 级别类型(由低到高)    # 是否可以避免脏读   # 是否可以避免不可重复读    # 是否可以避免幻读
  # read uncommitted          NO                      NO                  NO
  # read committed            YES                     NO                  NO
  # repeatable read           YES                     YES                 NO
  # serializable              YES                     YES                 YES
  # ---------------------------------------------------------------------------
  # serializable性能差,一个事务操作需要等待别的事务结束,一般使用默认事务级别(repeatable read)就可以了

# 查看mysql支持的存储引擎
show engines;
# 查看当前数据库的默认事务级别
select @@tx_isolation;
# 设置当前会话的隔离级别,只针对当前连接有效,语法:set session/global transaction isolation level 事务级别
set session transaction isolation level repeatable read;
# 查看当前数据库自动提交是否打开(on 是开启状态)
show variables like 'autocommit';

# 事务具体使用示例
set autocommit=0; # 关闭当前会话的事务自动提交功能
start transaction; # 开始事务,可选
insert into class (name, teacher) values ('九班', 'Bob');
savepoint rollback_tag; # 设置回滚节点,可选,语法:savepoint 节点名
insert into class (name, teacher) values ('十班', 'Bob');
rollback to rollback_tag; # 回滚到指定节点,可选,语法:rollback to 节点名
commit; #可以 commit 提交,也可以 rollback 回滚全部操作

# 事务针对delete删除,数据可回滚
set autocommit=0;
start transaction;
delete from class;
rollback;

#### 事务针对truncate删除,数据不可回滚
start transaction;
truncate table class;
rollback;

5、视图(view)

# 定义:mysql 5.1 出现的新特性,普通表一样,可以查询,某些情况下可以增删改(不推荐),
#      但是他是一种虚拟存在的表,是一个逻辑表,本身并不包含数据,
#      可以理解成是一个子sql,存储在mysql中,多条连接共享,重启mysql依然存在
# 用处:可以展示基表的部分数据
# 优点:简单、安全、数据独立,总而言之,使用视图的大部分情况是为了保障数据安全性,提高查询效率

# 视图创建,语法:create [or replace] view 视图名[(自取列名...)] as select语句;
#### 列名跟class表一样(当然这种视图是无意义的)
create view class_view as select name, teacher from class; 
#### 选取class里面的部分列,并且列名自定义
create view class_view(v_name, v_teacher) 
    as select name, teacher from class;
#### 连表数据构建一个view,查询出学生部分信息和其所在班级信息
create view student_view(id, name, class_name, class_teacher)
    as select s.id, s.name, c.name, c.teacher from student s 
        left join class c on s.classId=c.id;

# 视图查询,跟普通表查询一样
select * from class_view;
# 视图修改,语法:create or replace / alter 视图名 as select ....
create or replace view class_view as select * from class;
alter view test.class_view as select * from class;
# 视图删除,语法:drop view 视图名
drop view class_view;
# 视图查看
show create view class_view;
describe class_view;

6、临时表(temporary table)

# 定义:mysql 3.23 出现的新特性,用户自己定义的外部临时表,
#      这种临时表只对当前用户可见,当前会话结束的时候,该临时表会被自动销毁。
#      这种临时表的命名与非临时表可以同名(同名后非临时表将对当前会话不可见,直到临时表被删除)
# 用处:用来存储一些临时数据
# 有点:临时,连接断开就可以自动销毁

## 临时表的创建
create temporary table class_temp as select * from student;
## 临时表的删除
drop table class_temp;

7、变量

# 变量分为系统变量和用户自定义变量
  # 系统变量:变量由系统提供,不是用户定义的变量,分为全局变量和会话变量
    # 全局变量:针对本次启动全部连接都生效,mysql服务重启会被重置,修改会对新建连接的同名会话变量有影响,对已经建立连接的会话变量无影响
    # 会话变量:值针对本次连接生效,对其他连接无效,断开重连变量也会被重置
  # 自定义变量:用户自己定义的变量,分为用户变量和局部变量
    # 用户变量:作用域在当前会话,变量名前必须加@
    # 局部变量:只能在begin end第一句声明,并且只作用在当前begin end中

# 系统变量

## 全局变量
### 查看所有全局变量
show global variables;
### 查看满足条件的全局变量,语法:show global variables like xxx
show global variables like '%char%';
### 修改全局变量,语法:set global 变量名=变量值
set global autocommit=0;

## 会话变量
### 查看所有会话变量,语法:show [session] variables
show session variables;
show variables;
### 查看满足条件的会话变量,语法:show [session] variables like xxx
show variables like 'autocommit';
### 修改会话变量,语法:set [session] 变量名=变量值
set autocommit=0;

# 自定义变量

## 用户变量
### 自定义申明并初始化、更新有如下四种方式
  # set @变量名=值;
  # set @变量名:=值;
  # select @变量名:=值;
  # select 字段 into @变量名 from 表名....;
set @name='Tom';
set @age:=23;
select @classId:=2;
select grade into @grade from student where id=1;
### 自定义的用户变量输出,语法:select @变量名;
select @name, @age, @classId, @grade;

## 局部变量
### 声明 DECLARE 变量名 类型 [DEFAULT 值]
### 赋值
  # set 变量名=值;
  # set 变量名:=值;
  # select 变量名:=值
  # select 字段 into 变量名 from 表名....;
### 输出,语法:select 变量名;

8、存储过程

# 定义:一组预先编译好的SQL集合
# 好处:
#   存储的是编译好的代码块,执行效率要比T-SQL语句高
#   替代大堆的单个T-SQL语句,降低网络通信量,提高通信速率
#   通过存储过程能够使没有权限的用户在控制下间接地存取数据库,从而确保数据的安全

# 创建语法
  # create procedure 存储过程名(参数模式 参数名 参数类型, 参数模式 参数名 参数类型, ....)
  # begin
  #   存储过程体(一组合法的SQL语句)
  # end
  #
  # 参数模式可以分为 in、out、inout三种
  # in:传入参数,调用方传入
  # out:该参数可以作为返回值
  # inout:该参数既可以传入也可以作为返回值传出
  #
  # 下面来一组案例,查看某班分数在某一水平线下并且年级最小的学生,输出其姓名和真实分数
## 第一步. 使用 delimiter 指令将SQL语句的结束符号变成$,注意结尾没有";",只针对本次会话有效
delimiter $
## 第二步:创建存储过程
create procedure my_procedure (in classId int, out name varchar(20), inout grade int)
begin
    declare age int; # 定义一个局部变量,需要放在begin end第一样
    select min(s.age) into age from student s where s.classId=classId and s.grade

测试数据

drop table class;
drop table student;
drop table grade_level;

create table test.class
(
    id      int auto_increment comment '班级id'
        primary key,
    name    varchar(10) null comment '班级名称',
    teacher varchar(10) null comment '班主任'
)
    comment '班级表';

create table test.student
(
    id          int auto_increment comment '学生id'
        primary key,
    name        varchar(10)                        not null comment '学生姓名',
    age         int      default 0                 null comment '学生年龄',
    grander     char     default '0'               null comment '学生性别',
    grade       int      default 0                 null comment '成绩',
    classId     int      default 0                 not null comment '关联的班级id',
    create_time datetime default CURRENT_TIMESTAMP null comment '创建时间,默认为当前时间'
)
    comment '学生表';

create table test.grade_level
(
    id      int auto_increment comment 'id'
        primary key,
    level   char default 'A' null comment '等级,分为A、B...',
    l_grade int              null comment '该等级最低分数',
    h_grade int              null comment '该等级最高分数'
)
    comment '成绩等级表';

insert into test.class (name, teacher)
values  ('一班', 'Bob'),
        ('二班', 'John'),
        ('三班', 'Bob'),
        ('四班', 'Bob');

insert into test.student (name, age, grander, grade, classId)
values  ('Tom', 12, '男', 30, 1),
        ('Jerry', 24, '女', 88, 1),
        ('Anne', 12, '女', 70, 2),
        ('Rose', 23, '女', 90, 3),
        ('Lisa', 22, '女', 101, 5),
        ('Kevin', 24, '男', 78, 100);

insert into test.grade_level (level, l_grade, h_grade)
values  ('A', 81, 100),
        ('B', 61, 80),
        ('C', 0, 60);

select * from class;
select * from student;
select * from grade_level;

truncate class;
truncate student;
truncate grade_level;

你可能感兴趣的:(MySQL基础笔记)