• MySQL 学习笔记①



    若文章内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系博主删除。


    在这里插入图片描述


    • 强调黑马官方提供的 PDF 文档,内容非常详细。官方提供的 MD 文件 ,内容十分精简。

    写这篇博客旨在制作笔记,方便个人在线阅览,巩固知识。

    博客的内容主要来自视频内容和资料中提供的学习笔记。

    关于视频中出现的案例我则记录在了这篇博客里:《MySQL 学习笔记①_案例记录》


    0.总目录




    1.基本命令


    1.1.准备


    • 开启服务
    net start mysql80
    
    • 1
    • 关闭服务
    net stop mysql80
    
    • 1

    上述的 mysql80 是我们在安装 MySQL 时,默认指定的 mysql 的系统服务名,不是固定的。若未改动,默认是 mysql80。


    • 启动 MySQL(使用这种方式进行连接时,需要安装完毕后配置 PATH 环境变量。)
    mysql [-h 127.0.0.1] [-P 3306] -u root -p
    
    • 1
    • 参数:
      • -h:MySQL 服务所在的主机IP
      • -P:MySQL 服务端口号, 默认 3306
      • -u:MySQL 数据库用户名
      • -p:MySQL 数据库用户名对应的密码
    • [] 内为可选参数
      • 如果需要连接远程的 MySQL,需要加上这两个参数来指定远程主机IP、端口
      • 如果连接本地的 MySQL,则无需指定这两个参数。

    1.2.通用语法简介


    分类全称说明
    DDLData Definition Language数据定义语言,用来定义数据库对象(数据库、表、字段)
    DMLData Manipulation Language数据操作语言,用来对数据库表中的数据进行增删改
    DQLData Query Language数据查询语言,用来查询数据库中表的记录
    DCLData Contorl Language数据控制语言,用来创建数据库用户、控制数据库的控制权限

    1.3.DDL


    1.3.1.数据库操作


    • 查询所有数据库
    SHOW DATABASES;
    
    • 1
    • 查询当前数据库
    SELECT DATABASE();
    
    • 1
    • 创建数据库
    CREATE DATABASE [IF NOT EXISTS] 数据库名 [DEFAULT CHARSET 字符集] [COLLATE 排序规则];
    
    • 1
    • 删除数据库
    DROP DATABASE [IF EXISTS] 数据库名;
    
    • 1
    • 使用数据库
    USE 数据库名;
    
    • 1
    • 注意事项UTF8 字符集长度为 3 字节,有些符号占 4 字节,所以推荐用 utf8mb4 字符集

    1.3.2.表操作


    • 查询当前数据库所有表
    SHOW TABLES;
    
    • 1
    • 查询表结构
    DESC 表名;
    
    • 1
    • 查询指定表的建表语句
    SHOW CREATE TABLE 表名;
    
    • 1

    • 创建表
    CREATE TABLE 表名(
    	字段1 字段1类型 [COMMENT 字段1注释],
    	字段2 字段2类型 [COMMENT 字段2注释],
    	字段3 字段3类型 [COMMENT 字段3注释],
    	...
    	字段n 字段n类型 [COMMENT 字段n注释]
    )[ COMMENT 表注释 ];
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 注意事项:最后一个字段后面没有逗号

    • 添加字段
    ALTER TABLE 表名 ADD 字段名 类型(长度) [COMMENT 注释] [约束];
    
    • 1

    例:ALTER TABLE emp ADD nickname varchar(20) COMMENT '昵称';


    • 修改数据类型
    ALTER TABLE 表名 MODIFY 字段名 新数据类型(长度);
    
    • 1
    • 修改字段名和字段类型
    ALTER TABLE 表名 CHANGE 旧字段名 新字段名 类型(长度) [COMMENT 注释] [约束];
    
    • 1

    例:将 emp 表的 nickname 字段修改为 username,类型为 varchar(30)

    • ALTER TABLE emp CHANGE nickname username varchar(30) COMMENT '昵称';

    • 修改表名
    ALTER TABLE 表名 RENAME TO 新表名
    
    • 1

    • 删除字段
    ALTER TABLE 表名 DROP 字段名;
    
    • 1

    • 删除表
    DROP TABLE [IF EXISTS] 表名;
    
    • 1
    • 清空表数据,保留了表的结构
    TRUNCATE TABLE 表名;
    
    • 1

    1.4.DML


    • 添加数据(INSERT
    • 修改数据(UPDATE
    • 删除数据(DELETE

    1.4.1.添加数据


    • 指定字段
    INSERT INTO 表名 (字段名1, 字段名2, ...) VALUES (1,2, ...);
    
    • 1
    • 全部字段
    INSERT INTO 表名 VALUES (1,2, ...);
    
    • 1
    • 批量添加数据
    INSERT INTO 表名 (字段名1, 字段名2, ...) VALUES (1,2, ...), (1,2, ...), (1,2, ...);
    
    • 1
    INSERT INTO 表名 VALUES (1,2, ...), (1,2, ...), (1,2, ...);
    
    • 1
    • 注意事项
      • 插入数据时,指定的字段顺序需要与值的顺序是一一对应的。
      • 字符串和日期类型数据应该包含在引号中
      • 插入的数据大小应该在字段的规定范围内

    1.4.2.更新数据


    • 修改数据
    UPDATE 表名 SET 字段名1 =1, 字段名2 =2, ... [ WHERE 条件 ];
    
    • 1

    例:UPDATE emp SET name = 'Jack' WHERE id = 1;

    • 注意事项:修改语句的条件可以有,也可以没有,如果没有条件,则会修改整张表的所有数据。

    1.4.3.删除数据


    • 删除数据
    DELETE FROM 表名 [WHERE 条件];
    
    • 1
    • 注意事项
      • DELETE 语句的条件可以有,也可以没有。如果没有条件,则会删除整张表的所有数据。
      • DELETE 语句不能删除某一个字段的值(可以使用 UPDATE,将该字段值置为 NULL 即可)。

    1.5.DQL


    SELECT
    	字段列表
    FROM
    	表名字段
    WHERE
    	条件列表
    GROUP BY
    	分组字段列表
    HAVING
    	分组后的条件列表
    ORDER BY
    	排序字段列表
    LIMIT
    	分页参数
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    1.5.1.基础查询


    • 查询多个字段
    SELECT 字段1, 字段2, 字段3, ... FROM 表名;
    
    • 1
    SELECT * FROM 表名;
    
    • 1

    • 设置别名
    SELECT 字段1 [ AS 别名1 ], 字段2 [ AS 别名2 ], 字段3 [ AS 别名3 ], ... FROM 表名; 
    
    • 1

    上方代码块中的 as 可省略

    SELECT 字段1 [ 别名1 ], 字段2 [ 别名2 ], 字段3 [ 别名3 ], ... FROM 表名;
    
    • 1

    • 去除重复记录
    SELECT DISTINCT 字段列表 FROM 表名;
    
    • 1

    • 转义
    SELECT * FROM 表名 WHERE name LIKE '/_张三' ESCAPE '/'
    
    • 1

    / 之后的 _ 不作为通配符


    1.5.2.条件查询


    • 语法
    SELECT 字段列表 FROM 表名 WHERE 条件列表;
    
    • 1

    • 条件
    比较运算符功能
    >大于
    >=大于等于
    <小于
    <=小于等于
    =等于
    <> 或 !=不等于
    BETWEEN … AND …在某个范围内(含最小、最大值)
    IN(…)在in之后的列表中的值,多选一
    LIKE 占位符模糊匹配( _ 匹配单个字符,% 匹配任意个字符 )
    IS NULL是 NULL
    逻辑运算符功能
    AND 或 &&并且(多个条件同时成立)
    OR 或 ||或者(多个条件任意一个成立)
    NOT 或 !非,不是

    1.5.3.聚合查询(聚合函数


    将一列数据作为一个整体,进行纵向计算 。


    常见聚合函数

    函数功能
    count统计数量
    max最大值
    min最小值
    avg平均值
    sum求和

    • 语法
    SELECT 聚合函数(字段列表) FROM 表名;
    
    • 1
    • 例:SELECT count(id) from employee where workaddress = "广东省";
    • 注意NULL 值是不参与所有聚合函数运算的。

    1.5.4.分组查询


    • 语法
    SELECT 字段列表 FROM 表名 [ WHERE 条件 ] GROUP BY 分组字段名 [ HAVING 分组后的过滤条件 ];
    
    • 1

    • wherehaving 的区别
      • 执行时机不同:where 是分组之前进行过滤,不满足 where 条件不参与分组;having 是分组后对结果进行过滤。
      • 判断条件不同:where 不能对聚合函数进行判断,而 having 可以。

    • 注意事项
      • 分组之后,查询的字段一般为聚合函数和分组字段,查询其他字段无任何意义。
      • 执行顺序:where > 聚合函数 > having
      • 支持多字段分组, 具体语法为 group by columnA, columnB

    -- 根据性别分组,统计男性和女性数量(只显示分组数量,不显示哪个是男哪个是女)
    select count(*) from employee group by gender;
    
    • 1
    • 2
    -- 根据性别分组,统计男性和女性数量
    select gender, count(*) from employee group by gender;
    
    • 1
    • 2
    -- 根据性别分组,统计男性和女性的平均年龄
    select gender, avg(age) from employee group by gender;
    
    • 1
    • 2
    -- 年龄小于 45,并根据工作地址分组
    select workaddress, count(*) from employee where age < 45 group by workaddress;
    
    • 1
    • 2
    -- 年龄小于 45,并根据工作地址分组,获取员工数量大于等于 3 的工作地址
    select workaddress, count(*) address_count from employee where age < 45 group by workaddress having address_count >= 3;
    
    • 1
    • 2

    1.5.5.排序查询


    • 语法
    SELECT 字段列表 FROM 表名 ORDER BY 字段1 排序方式1, 字段2 排序方式2;
    
    • 1

    • 排序方式
      • ASC:升序(默认)
      • DESC:降序

    • 注意事项:如果是多字段排序,当第一个字段值相同时,才会根据第二个字段进行排序

    1.5.6.分页查询


    • 语法
    SELECT 字段列表 FROM 表名 LIMIT 起始索引, 查询记录数;
    
    • 1

    • 注意事项
      • 起始索引从 0 开始。起始索引 = (查询页码 - 1) * 每页显示记录数
      • 分页查询是数据库的方言,不同数据库有不同实现,MySQL 是 LIMIT
      • 如果查询的是第一页数据,起始索引可以省略,直接简写 LIMIT 10

    1.5.7.DQL 执行顺序


    • 执行顺序:FROM -> WHERE -> GROUP BY -> SELECT -> ORDER BY -> LIMIT

    在这里插入图片描述


    1.6.DCL


    1.6.1.管理用户


    • 查询用户
    USE mysql;
    
    • 1
    SELECT * FROM user;
    
    • 1
    • 创建用户
    CREATE USER '用户名'@'主机名' IDENTIFIED BY '密码';
    
    • 1
    • 修改用户密码
    ALTER USER '用户名'@'主机名' IDENTIFIED WITH mysql_native_password BY '新密码';
    
    • 1
    • 删除用户
    DROP USER '用户名'@'主机名';
    
    • 1

    在这里插入图片描述

    • 其中 Host 代表当前用户访问的主机。
    • 如果为 localhost,仅代表只能够在当前本机访问,是不可以远程访问的。
    • User 代表的是访问该数据库的用户名。
    • 在 MySQL 中需要通过 Host 和 User 来唯一标识一个用户。

    • 注意事项
      • 在 MySQL 中需要通过 用户名@主机名 的方式,来唯一标识一个用户。
      • 主机名可以使用 % 通配。
      • 这类 SQL 开发人员操作的比较少,主要是 DBA( Database Administrator,即数据库管理员)使用。

    1.6.2.权限控制


    MySQL 中定义了很多种权限,但是常用的就以下几种

    权限说明
    ALL,ALL PRIVILEGES所有权限
    SELECT查询数据
    INSERT插入数据
    UPDATE修改数据
    DELETE删除数据
    ALTER修改表
    DROP删除数据库/表/视图
    CREATE创建数据库/表

    上述只是简单罗列了常见的几种权限描述,其他权限描述及含义,可以直接参考官方文档


    1. 查询权限
    SHOW GRANTS FOR '用户名'@'主机名' ;
    
    • 1

    1. 授予权限
    GRANT 权限列表 ON 数据库名.表名 TO '用户名'@'主机名';
    
    • 1

    1. 撤销权限
    REVOKE 权限列表 ON 数据库名.表名 FROM '用户名'@'主机名';
    
    • 1

    • 注意事项
      • 多个权限之间,使用逗号分隔
      • 授权时, 数据库名和表名可以使用 * 进行通配,代表所有。

    2.函数


    2.1.字符串函数


    常用函数

    函数功能
    CONCAT(s1, s2, …, sn)字符串拼接,将 s1, s2, …, sn 拼接成一个字符串
    LOWER(str)将字符串全部转为小写
    UPPER(str)将字符串全部转为大写
    LPAD(str, n, pad)左填充,用字符串 pad 对 str 的左边进行填充,达到 n 个字符串长度
    RPAD(str, n, pad)右填充,用字符串 pad 对 str 的右边进行填充,达到 n 个字符串长度
    TRIM(str)去掉字符串头部和尾部的空格
    SUBSTRING(str, start, len)返回从字符串 str 从 start 位置起的 len 个长度的字符串

    -- 拼接
    SELECT CONCAT('Hello', 'World');
    
    • 1
    • 2
    -- 小写
    SELECT LOWER('Hello');
    
    • 1
    • 2
    -- 大写
    SELECT UPPER('Hello');
    
    • 1
    • 2
    -- 左填充
    SELECT LPAD('01', 5, '-');
    
    • 1
    • 2
    -- 右填充
    SELECT RPAD('01', 5, '-');
    
    • 1
    • 2
    -- 去除首尾的空格
    SELECT TRIM(' Hello World ');
    
    • 1
    • 2
    -- 切片(注意,该函数的起始索引为 1)
    SELECT SUBSTRING('Hello World', 1, 5);
    
    • 1
    • 2

    2.2.数值函数


    常见函数

    函数功能
    CEIL(x)向上取整
    FLOOR(x)向下取整
    MOD(x, y)返回 x/y 的模
    RAND()返回 0~1 内的随机数
    ROUND(x, y)求参数 x 的四舍五入值,保留 y 位小数
    -- 向上取整
    SELECT CEIL(1.1);
    
    • 1
    • 2
    -- 向下取整
    SELECT FLOOR(1.9);
    
    • 1
    • 2
    -- 取模
    SELECT MOD(7,4);
    
    • 1
    • 2
    -- 获取随机数
    SELECT RAND();
    
    • 1
    • 2
    -- 四舍五入
    SELECT ROUND(2.344,2);
    
    • 1
    • 2

    2.3.日期函数


    常用函数

    函数功能
    CURDATE()返回当前日期
    CURTIME()返回当前时间
    NOW()返回当前日期和时间
    YEAR(date)获取指定 date 的年份
    MONTH(date)获取指定 date 的月份
    DAY(date)获取指定 date 的日期
    DATE_ADD(date, INTERVAL expr type)返回一个日期/时间值加上一个时间间隔 expr 后的时间值
    DATEDIFF(date1, date2)返回起始时间 date1 和结束时间 date2 之间的天数

    SELECT CURDATE();
    
    • 1
    SELECT CURTIME();
    
    • 1
    SELECT NOW();
    
    • 1

    SELECT YEAR(NOW());
    
    • 1
    SELECT MONTH(NOW());
    
    • 1
    SELECT DAY(NOW());
    
    • 1

    SELECT DATE_ADD(NOW(), INTERVAL 70 YEAR );
    
    • 1
    SELECT DATEDIFF('2021-10-01', '2021-12-01');
    
    • 1

    2.4.流程函数


    常用函数

    函数功能
    IF(value, t, f)如果 value 为 true,则返回 t,否则返回 f
    IFNULL(value1, value2)如果 value1 不为空,返回 value1,否则返回 value2
    CASE WHEN [ val1 ] THEN [ res1 ] … ELSE [ default ] END如果 val1 为 true,返回 res1,… 否则返回 default 默认值
    CASE [ expr ] WHEN [ val1 ] THEN [ res1 ] … ELSE [ default ] END如果 expr 的值等于 val1,返回 res1,… 否则返回 default 默认值

    SELECT
    	name,
    	(CASE WHEN age > 30 THEN '中年' ELSE '青年' END) AS '青年/中年'
    FROM employee;
    
    • 1
    • 2
    • 3
    • 4
    select
    	name,
    	(case workaddress when '北京市' then '一线城市' when '上海市' then '一线城市' else '二线城市' end) as '工作地址'
    from employee;
    
    • 1
    • 2
    • 3
    • 4

    3.约束


    概念:约束是作用于表中字段上的规则,用于限制存储在表中的数据。

    目的:保证数据库中数据的正确、有效性和完整性。


    3.1.约束分类


    约束描述关键字
    非空约束限制该字段的数据不能为 nullNOT NULL
    唯一约束保证该字段的所有数据都是唯一、不重复的UNIQUE
    主键约束主键是一行数据的唯一标识,要求非空且唯一PRIMARY KEY
    默认约束保存数据时,如果未指定该字段的值,则采用默认值DEFAULT
    检查约束(8.0.1 版本后)保证字段值满足某一个条件CHECK
    外键约束用来让两张图的数据之间建立连接,保证数据的一致性和完整性FOREIGN KEY
    • 注意事项:约束是作用于表中字段上的,可以在 创建表/修改表 的时候添加约束。

    3.2.常用约束


    约束条件关键字
    主键PRIMARY KEY
    自动增长AUTO_INCREMENT
    不为空NOT NULL
    唯一UNIQUE
    逻辑条件CHECK
    默认值DEFAULT

    create table user(
    	id int primary key auto_increment,
    	name varchar(10) not null unique,
    	age int check(age > 0 and age < 120),
    	status char(1) default '1',
    	gender char(1)
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    3.3.外键约束


    外键:用来让两张表的数据之间建立连接,从而保证数据的一致性和完整性。


    3.3.1.添加外键


    CREATE TABLE 表名(
    	字段名 字段类型,
    	...
    	[CONSTRAINT] [外键名称] FOREIGN KEY(外键字段名) REFERENCES 主表(主表列名)
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY (外键字段名) REFERENCES 主表(主表列名);
    
    • 1
    • 如:alter table emp add constraint fk_emp_dept_id foreign key(dept_id) references dept(id);

    3.3.2.删除外键


    ALTER TABLE 表名 DROP FOREIGN KEY 外键名;
    
    • 1

    3.2.3.删除/更新行为


    行为说明
    NO ACTION当在父表中删除/更新对应记录时,首先检查该记录是否有对应外键,如果有则不允许删除/更新(与 RESTRICT 一致)
    RESTRICT当在父表中删除/更新对应记录时,首先检查该记录是否有对应外键,如果有则不允许删除/更新(与 NO ACTION 一致)
    CASCADE当在父表中删除/更新对应记录时,首先检查该记录是否有对应外键,如果有则也删除/更新外键在子表中的记录
    SET NULL当在父表中删除/更新对应记录时,首先检查该记录是否有对应外键,如果有则设置子表中该外键值为 null(要求该外键允许为 null)
    SET DEFAULT父表有变更时,子表将外键设为一个默认值(Innodb 不支持)

    • 具体语法(更改删除/更新行为)
    ALTER TABLE 表名 
    	ADD CONSTRAINT 外键名称 FOREIGN KEY (外键字段) REFERENCES 主表名(主表字段名) 
    	ON UPDATE 行为 
    	ON DELETE 行为;
    
    • 1
    • 2
    • 3
    • 4

    4.多表查询


    4.1.多表关系


    多表关系

    • 一对多(多对一)、多对多、一对一

    一对多

    • 案例:部门与员工
    • 关系:一个部门对应多个员工,一个员工对应一个部门
    • 实现:在多的一方建立外键,指向一的一方的主键

    在这里插入图片描述


    多对多

    • 案例:学生与课程
    • 关系:一个学生可以选多门课程,一门课程也可以供多个学生选修
    • 实现:建立第三张中间表,中间表至少包含两个外键,分别关联两方主键

    在这里插入图片描述


    一对一

    • 案例:用户与用户详情
    • 关系:一对一关系,多用于单表拆分,将一张表的基础字段放在一张表中,其他详情字段放在另一张表中,以提升操作效率
    • 实现:在任意一方加入外键,关联另外一方的主键,并且设置外键为唯一的(UNIQUE)

    在这里插入图片描述


    4.2.多表查询概述


    多表查询就是指从多张表中查询数据。

    原来查询单表数据,执行的 SQL 形式为:select * from emp;

    那么我们要执行多表查询,就只需要使用逗号分隔多张表即可,如:select * from emp , dept;

    在这里插入图片描述

    如上所示,我们看到查询结果中包含了大量的结果集,总共 102 条记录。(dept 表共 6 条记录,emp 表共17条记录。)

    这其实就是员工表 emp 所有的记录(17)与 部门表 dept 所有记录(6)的所有组合情况,这种现象称之为笛卡尔积


    笛卡尔积:笛卡尔乘积是指在数学中,两个集合(A 集合 和 B 集合)的所有组合情况。

    在这里插入图片描述


    在多表查询中,我们是需要消除无效的笛卡尔积的,只保留两张表关联部分的数据。

    在这里插入图片描述


    在 SQL 语句中,如何来去除无效的笛卡尔积呢? 我们可以给多表查询加上连接查询的条件即可。

    SELECT * FROM emp , dept WHERE emp.dept_id = dept.id;
    
    • 1

    在这里插入图片描述


    4.3.分类


    连接查询

    • 内连接:相当于查询 A、B 交集部分数据
    • 外连接
      • 左外连接:查询左表所有数据,以及两张表交集部分数据
      • 右外连接:查询右表所有数据,以及两张表交集部分数据
      • 自连接:当前表与自身的连接查询,自连接必须使用表别名

    子查询:嵌套在其他查询中的查询


    4.4.连接查询


    4.4.1.内连接查询


    内连接查询的是两张表交集部分的数据。(也就是绿色部分的数据)

    内连接的语法分为两种: 隐式内连接、显式内连接。

    在这里插入图片描述


    1. 隐式内连接
    SELECT 字段列表 FROM1 ,2 WHERE 条件 ... ;
    
    • 1
    1. 显式内连接
    SELECT 字段列表 FROM1 [ INNER ] JOIN2 ON 连接条件 ... ;
    
    • 1

    • 查询每一个员工的姓名,及关联的部门的名称(隐式内连接实现)
    • 表结构:emp , dept
    • 连接条件:emp.dept_id = dept.id
    SELECT emp.name , dept.name FROM emp , dept WHERE emp.dept_id = dept.id;
    
    • 1
    -- 为每一张表起别名,简化 SQL 编写
    SELECT e.name, d.name FROM emp e , dept d WHERE e.dept_id = d.id;
    
    • 1
    • 2

    • 查询每一个员工的姓名 , 及关联的部门的名称(显式内连接实现)
      • INNER JOIN …ON …
    • 表结构:emp , dept
    • 连接条件:emp.dept_id = dept.id
    SELECT e.name, d.name FROM emp e INNER JOIN dept d ON e.dept_id = d.id;
    
    • 1
    -- 为每一张表起别名,简化 SQL 编写
    SELECT e.name, d.name FROM emp e JOIN dept d ON e.dept_id = d.id;
    
    • 1
    • 2

    表的别名

    • tablea as 别名1, tableb as 别名2;

    • tablea 别名1, tableb 别名2;

    • 注意事项:一旦为表起了别名,就不能再使用表名来指定对应的字段了,此时只能够使用别名来指定字段。


    4.4.2.外连接查询


    左外连接相当于查询表1(左表)的所有数据,当然也包含表1和表2交集部分的数据。

    SELECT 字段列表 FROM1 LEFT [ OUTER ] JOIN2 ON 条件 ... ;
    
    • 1

    右外连接相当于查询表2(右表)的所有数据,当然也包含表1和表2交集部分的数据。

    SELECT 字段列表 FROM1 RIGHT [ OUTER ] JOIN2 ON 条件 ... ;
    
    • 1

    RIGHT 指出的是 OUTER JOIN 右边的表,lEFT 指出的是 OUTER JOIN 左边的表。


    • 注意事项
      • 左外连接和右外连接是可以相互替换的,只需要调整在连接查询时 SQL 中,表结构的先后顺序就可以了。
      • 我们在日常开发使用时,更偏向于左外连接。

    4.4.3.自连接查询


    自连接查询,顾名思义,就是自己连接自己,也就是把一张表连接查询多次。

    SELECT 字段列表 FROM 表A 别名A JOIN 表A 别名B ON 条件 ... ;
    
    • 1

    对于自连接查询,可以是内连接查询,也可以是外连接查询。


    • 注意事项
      • 在自连接查询中,必须要为表起别名
      • 要不然我们不清楚所指定的条件、返回的字段,到底是哪一张表的字段。

    4.7.联合查询


    对于 union 查询,就是把多次查询的结果合并起来,形成一个新的查询结果集。

    SELECT 字段列表 FROM 表A ...
    UNION [ ALL ]
    SELECT 字段列表 FROM 表B ....;
    
    • 1
    • 2
    • 3
    • 对于联合查询的多张表的列数必须保持一致,字段类型也需要保持一致。
    • union all 会将全部的数据直接合并在一起,union 会对合并之后的数据去重。

    • 注意:如果多条查询语句查询出来的结果,字段数量不一致,在进行 union/union all 联合查询时,将会报错。

    在这里插入图片描述


    4.8.子查询


    4.8.1.概述


    SQL 语句中嵌套 SELECT 语句,称为嵌套查询,又称子查询。

    SELECT * FROM t1 WHERE column1 = ( SELECT column1 FROM t2 );
    
    • 1

    子查询外部的语句可以是 INSERT / UPDATE / DELETE / SELECT 的任何一个。


    根据子查询结果可以分为:

    • 标量子查询(子查询结果为单个值)
    • 列子查询(子查询结果为一列)
    • 行子查询(子查询结果为一行)
    • 表子查询(子查询结果为多行多列)

    根据子查询位置可分为:

    • WHERE 之后
    • FROM 之后
    • SELECT 之后

    4.8.2.标量子查询


    子查询返回的结果是单个值(数字、字符串、日期等),最简单的形式,这种子查询称为标量子查询。


    常用的操作符:=<>>>=<<=


    -- 查询销售部所有员工
    select id from dept where name = '销售部';
    
    • 1
    • 2
    -- 根据销售部部门 ID,查询员工信息
    select * from employee where dept = 4;
    
    • 1
    • 2
    -- 合并(子查询)
    select * from employee where dept = (select id from dept where name = '销售部');
    
    • 1
    • 2

    -- 查询入职时间在 xxx 入职时间之后的员工信息
    select * from employee where entrydate > (select entrydate from employee where name = 'xxx');
    
    • 1
    • 2

    4.8.3.列子查询


    子查询返回的结果是一列(可以是多行),这种子查询称为列子查询。


    常用的操作符:INNOT INANYSOMEALL


    常用操作符

    操作符描述
    IN在指定的集合范围内,多选一
    NOT IN不在指定的集合范围内
    ANY子查询返回列表中,有任意一个满足即可
    SOME与 ANY 等同,使用 SOME 的地方都可以使用 ANY
    ALL子查询返回列表的所有值都必须满足

    例:查询销售部和市场部的所有员工信息

    select * from employee where dept in (select id from dept where name = '销售部' or name = '市场部');
    
    • 1

    例:查询比财务部所有人工资都高的员工信息

    select * from employee where salary > all(select salary from employee where dept = (select id from dept where name = '财务部'));
    
    • 1

    例:查询比研发部任意一人工资高的员工信息

    select * from employee where salary > any (select salary from employee where dept = (select id from dept where name = '研发部'));
    
    • 1

    4.8.4.行子查询


    子查询返回的结果是一行(可以是多列),这种子查询称为行子查询。


    常用的操作符:=<>INNOT IN


    例:查询与 xxx 的薪资及直属领导相同的员工信息

    select * from employee where (salary, manager) = (12500, 1);
    
    • 1
    select * from employee where (salary, manager) = (select salary, manager from employee where name = 'xxx');
    
    • 1

    4.8.5.表子查询


    返回的结果是多行多列


    常用操作符:IN


    例:查询与 xxx1,xxx2 的职位和薪资相同的员工

    select * from employee where (job, salary) in (select job, salary from employee where name = 'xxx1' or name = 'xxx2');
    
    • 1

    例:查询入职日期是 2006-01-01 之后的员工,及其部门信息

    select e.*, d.* from (select * from employee where entrydate > '2006-01-01') as e left join dept as d on e.dept = d.id;
    
    • 1

    5.事务


    5.1.概念


    事务是一组操作的集合,它是一个不可分割的工作单位。

    事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求。即这些操作要么同时成功,要么同时失败。

    • 注意
      • 默认 MySQL 的事务是自动提交的。
      • 即当执行完一条 DML 语句时,MySQL 会立即隐式的提交事务。

    5.2.测试


    1. 测试正常情况
    -- 1. 查询张三余额
    SELECT * FROM account WHERE NAME = '张三';
    
    -- 2. 张三的余额减少 1000
    UPDATE account SET money = money - 1000 WHERE NAME = '张三';
    
    -- 3. 李四的余额增加 1000
    UPDATE account SET money = money + 1000 WHERE NAME = '李四';
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述


    1. 测试异常情况
    -- 1. 查询张三余额
    select * from account where name = '张三';
    
    -- 2. 张三的余额减少 1000
    update account set money = money - 1000 where name = '张三';
    
    出错啦...
    -- 3. 李四的余额增加 1000
    update account set money = money + 1000 where name = '李四';
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述


    5.3.事务操作


    • 查看事务的提交方式(1 为自动提交;0 为手动提交)
    SELECT @@autocommit ;
    
    • 1

    • 设置事务的提交方式(1 为自动提交;0 为手动提交)
    SET @@autocommit = 0 ;
    
    • 1

    • 手动开启事务(以下两条语句都可以)
    START TRANSACTION 
    
    • 1
    BEGIN TRANSACTION;
    
    • 1

    • 提交事务
    COMMIT;
    
    • 1
    • 回滚
    ROLLBACK;
    
    • 1

    • 注意事项
      • 当我们修改了事务的自动提交行为(把默认的自动提交修改为了手动提交)
      • 此后我们执行的 DML 语句都不会提交, 需要手动的执行 commit 进行提交。

    5.2.四大特性


    以下是事务的四大特性,简称 ACID

    • 原子性Atomicity):事务是不可分割的最小操作但愿,要么全部成功,要么全部失败
    • 一致性Consistency):事务完成时,必须使所有数据都保持一致状态
    • 隔离性Isolation):数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行
    • 持久性Durability):事务一旦提交或回滚,它对数据库中的数据的改变就是永久的

    5.3.并发事务


    5.3.1.并发事务问题


    问题描述
    脏读一个事务读到另一个事务还没提交的数据
    不可重复读一个事务先后读取同一条记录,但两次读取的数据不同
    幻读一个事务按照条件查询数据时,没有对应的数据行,但是再插入数据时,又发现这行数据已经存在

    这三个问题的详细演示:基础-事务-并发事务问题(视频 P55 里讲的很清楚,这个视频最好看完)


    1. 赃读:一个事务读到另外一个事务还没有提交的数据。

    比如

    • 事务 A 对数据进行了修改并提交,事务 B 读到了 事务 A 提交后的数据。
    • 但是事务 B 因为某种原因被撤销(比如回滚操作)了,最终事务 B 读到的数据与数据库中存储的数据并不一致。

    在这里插入图片描述


    1. 不可重复读:一个事务先后读取同一条记录,但两次读取的数据不同,称之为不可重复读。

    在这里插入图片描述
    事务 A 两次读取同一条记录,但是读取到的数据却是不一样的


    1. 幻读:一个事务按照条件查询数据时,没有对应的数据行,但是在插入数据时,又发现这行数据已经存在,好像出现了 “幻影”。

    在这里插入图片描述


    5.3.2.并发事务隔离级别


    隔离级别脏读不可重复读幻读
    Read uncommitted
    Read committed×
    Repeatable Read(默认)××
    Serializable×××
    • 表示在当前隔离级别下该问题会出现
    • Serializable 性能最低;Read uncommitted 性能最高,数据安全性最差

    • 查看事务隔离级别
    SELECT @@TRANSACTION_ISOLATION;
    
    • 1
    • 设置事务隔离级别
    SET [ SESSION | GLOBAL ] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE };
    
    • 1

    SESSION 是会话级别,表示只针对当前会话有效,GLOBAL 表示对所有会话有效


    • 注意事项:事务隔离级别越高,数据越安全,但是性能越低。

  • 相关阅读:
    关于SQL的返回行数top
    第8章:React生命周期
    xilinx primitives(原语)
    VUE [入门篇(三)]
    Flink——监控
    股票买进和卖出手续费怎么算,一文看懂,不用研究那些旧规则了
    mysql、sqlserver数据库之间的数据同步
    基于SSM的社区疫情居民信息登记系统
    计算机毕设 基于大数据的服务器数据分析与可视化系统 -python 可视化 大数据
    wxWidgets(1):在Ubuntu 环境中搭建wxWidgets 库环境,安装库和CodeBlocks的IDE,可以运行demo界面了,继续学习中
  • 原文地址:https://blog.csdn.net/yanzhaohanwei/article/details/127331263