MySQL终章

本文详细介绍了DQL(数据查询语言)的各种操作,包括基本查询、分组查询、排序、条件限制、子查询以及表连接等。通过实例展示了如何使用SQL进行数据的筛选、聚合、连接和分页操作,强调了在实际应用中的注意事项和最佳实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

6. 查询语句【重点】DQL
6.1 使用数据库数据表信息结构概述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Zplh0LGz-1680436436518)(img/02-company数据库表结构信息概述.png)]

6.2 基本格式
select 查询内容 from 从哪里查;
-- 查询内容,字段名,列名,field
-- 从哪里查,表名 tableName
6.2.1 基本格式 字段表名
-- * 通配符,可以用于通配字段,所有字段
-- 不建议使用,会导致数据量过大,查询周期过长,MySQL 压力过大
-- 从员工表 t_employees 中 所有的员工数据信息
select *
from t_employees;

-- 指定字段查询,明确当前查询操作指定的字段名称,数据需求。
-- 查询所有员工的名字,姓氏和id数据
select employee_id, first_name, last_name
from t_employees;
6.2.2 查询结果字段数据进行计算操作
-- 员工表中,字段 salary 为月薪,这里可以计算年薪 * 12、
-- 查询所有员工的id,名字,姓氏和年薪
select employee_id, first_name, last_name, salary * 12
from t_employees;

select employee_id, first_name, last_name, salary
from t_employees;
6.2.3 查询结果字段数据去重操作
-- 查询所有员工的姓氏 resultSet 结果集数据行 107 rows
select last_name
from t_employees;

-- 查询所有员工的姓氏,并且去重,指定字段的数据内容在数据结果中有且只有一个
-- resultSet 结果集数据行 102 rows
select distinct last_name
from t_employees;
6.2.4 查询结果字段别名处理
-- 查询字段的名称目前是按照数据表中设计的字段名称进行处理
-- 数据表字段名称不方便,或者说解析阅读性一般
-- 查询所有员工的 last_name【别名】 姓,first_name【别名】名,salary 【别名】工资
select last_name  as '姓',
       first_name as '名',
       salary     as '工资'
from t_employees;
6.3 排序查询 order by
规则效果
asc约束指定字段【升序】排序查询结果内容
desc约束指定字段【降序】排序查询结果内容
-- 基本格式
select fieldName1, fieldName2
from tableName
order by fieldName condition;
6.3.1 单一条件排序
-- 按照工资进行升序排序,要求查询结果字段包括 employee_id, first_name, last_name, salary
-- IDEA 提示 asc 有警告: order by 操作默认升序,可以省略 asc 标记
select employee_id, first_name, last_name, salary
from t_employees
order by salary asc;

-- 与上方的查询要求一致,order by 默认指定字段升序
select employee_id, first_name, last_name, salary
from t_employees
order by salary;

-- order by 排序要求使用的字段,与当前查询目标字段无关,
-- 字段数据,字段信息可以从指定表直接获取
-- 当前查询没有 salary 字段数据要求,但是排序是按照 salary 字段信息完成
-- 【注意】后期查询限制条件众多,需要明确查询限制的字段信息从何而来
select employee_id, first_name, last_name
from t_employees
order by salary;

-- 按照工资进行降序排序,要求查询结果字段包括 employee_id, first_name, last_name, salary
select employee_id, first_name, last_name, salary
from t_employees
order by salary desc;
6.3.2 多条件排序
-- 排序操作采用多个字段进行排序操作
-- 例如: 第一个字段降序,如果按照第一个字段数据限制
-- 出现了相同数据的形式,按照第二个字段进行再次排序

-- 按照工资进行降序排序,要求查询结果字段包括 employee_id, first_name, last_name, salary
-- 如果出现了工资一致情况,按照  employee_id 降序
select employee_id, first_name, last_name, salary
from t_employees
order by salary desc, employee_id desc;
6.4 where 条件限制查询
6.4.1 基本格式
select fieldName 
from tbName
where condition;
-- 要求从指定数据表中,获取指定字段数据内容
-- where 限制查询条件,条件要求为 boolean
6.4.2 等值判断 =
-- SQL 语句指定字段是否和目标数据内容一致 = 判断
-- 可以判断数值类型,也可以判断字符串类型

-- 在员工表中查询 employee_id. first_name, last_name, salary 要求 salary 为 2500
-- 数值类型数据 = 判断
select employee_id, first_name, last_name, salary
from t_employees
where salary = 2500;

-- 在员工表中查询 employee_id. first_name, last_name, salary 要求 部门id 为 80
-- 数值类型数据 = 判断
select employee_id, first_name, last_name, salary
from t_employees
where department_id = 80;

-- 在员工表中查询 employee_id. first_name, last_name, salary 要求 last_name 为 King
-- 字符串类型数据 = 判断
select employee_id, first_name, last_name, salary
from t_employees
where last_name = 'King';

-- 字符串判断不区分大小写
select employee_id, first_name, last_name, salary
from t_employees
where last_name = 'king';
6.4.3 不等值判断(> < >= <= != <>)
-- != 不等于
-- <> 不等于,并且支持 SQL 所有版本 【更合适】

-- 在员工表中查询 employee_id. first_name, last_name, salary,要求 salary 在 大于等于 10000
select employee_id, first_name, last_name, salary
from t_employees
where salary >= 10000;

-- 在员工表中查询 employee_id. first_name, last_name, salary,要求 employee_id 小于等于 120
select employee_id, first_name, last_name, salary
from t_employees
where employee_id <= 120;

-- 在员工表中查询 employee_id. first_name, last_name, salary,要求部门id 不为 80
-- != 操作
select employee_id, first_name, last_name, salary
from t_employees
where department_id != 80;

-- 在员工表中查询 employee_id. first_name, last_name, salary,要求部门id 不为 80
-- <> 操作,版本适应性更强
select employee_id, first_name, last_name, salary
from t_employees
where department_id <> 80;
6.4.4 逻辑判断(and, or, not)
-- and or not ==> 相当于 && || !
-- 特定情况下可以等价替换

-- 在员工表中查询,找出 employee_id, first_name, last_name, salary,  要求工资在 8000 ~ 10000
-- and 与连接
select employee_id, first_name, last_name, salary
from t_employees
where salary >= 8000
  and salary <= 10000;

-- && 与连接
select employee_id, first_name, last_name, salary
from t_employees
where salary >= 8000 && salary <= 10000;

-- 在员工表中查询,找出 employee_id, first_name, last_name, salary, commission_pct 要求工资在 大于 10000 或者 提成高于 0.2
-- or 或连接
select employee_id, first_name, last_name, salary, commission_pct
from t_employees
where salary >= 10000 or commission_pct > 0.2;

-- || 或连接
select employee_id, first_name, last_name, salary, commission_pct
from t_employees
where salary >= 10000 || commission_pct > 0.2;

-- 在员工表中查询,找出 employee_id, first_name, last_name, salary,  要求工资不等于 8000
-- != 不等于判断,可以使用
select employee_id, first_name, last_name, salary
from t_employees
where salary != 8000;

-- not 限制,需要在字段之前
select employee_id, first_name, last_name, salary
from t_employees
where not salary = 8000;

-- 无法使用 ! 替换 not
-- 【查无结果,错误演示】
select employee_id, first_name, last_name, salary
from t_employees
where ! salary = 8000;
6.4.5 区间(between and)
-- SQL 中区间限制
-- 格式 between min and max,要求 between 之后是小数值,and 之后是大数值,数据不按照要求,报错
-- 并且 min <= n <= max
-- n >= min && n <= max 或者 n >= min and n <= max

-- 在员工表中查询,找出 employee_id, first_name, last_name, salary,  要求工资在 8000 ~ 10000 之间
select employee_id, first_name, last_name, salary
from t_employees
where salary between 8000 and 10000;

-- 数据没有结果,没有按照前小后大要求
select employee_id, first_name, last_name, salary
from t_employees
where salary between 10000 and 8000;

select employee_id, first_name, last_name, salary
from t_employees
where salary >= 8000 and salary <= 10000;

-- 在员工表中查询,找出 employee_id, first_name, last_name, salary,
-- 要求工资在 8000 ~ 10000 之间,并且按照工资降序
select employee_id, first_name, last_name, salary
from t_employees
where salary between 8000 and 10000 -- 区间查询
order by salary desc; -- 区间结果排序限制
6.4.6 null 值判断
-- null 在数据库中是空值,表示当前字段没有数据
-- id
-- 0    表示当前 id 字段数据为 0
-- null 表示当前 id 字段没有数据
-- 常用判断
-- is null     判断指定字段是 null
-- is not null 判断指定字段不是 null

-- 在员工表中查询,找出 employee_id, first_name, commission_pct, 要求 commission_pct 为 null
-- is null
select employee_id, first_name, commission_pct
from t_employees
where commission_pct is null;

-- 在员工表中查询,找出 employee_id, first_name, commission_pct, 要求 commission_pct 不是 null
-- is not null
select employee_id, first_name, commission_pct
from t_employees
where commission_pct is not null;
6.4.7 枚举查询 in
-- 找出员工表中,所有的部门 id 号,distinct 去重操作
select distinct department_id
from t_employees;

-- 在员工表中查询,找出 employee_id, first_name, department_id, 限制部门id为 80 50 20
select employee_id, first_name, department_id
from t_employees
where department_id = 80
   or department_id = 50
   or department_id = 20;

-- 在员工表中查询,找出 employee_id, first_name, department_id, 限制部门id为 80 50 20
-- 按照枚举 in 的方式来操作
-- in (数据), 要求找出指定字段在 小括号 () 数据对应所有数据行
select employee_id, first_name, department_id
from t_employees
where department_id in (20, 50, 80);

-- 在员工表中查询,找出 employee_id, first_name, department_id, 限制部门id不是 80 50 20
select employee_id, first_name, department_id
from t_employees
where department_id != 80
  and department_id != 50
  and department_id != 20;

-- 在员工表中查询,找出 employee_id, first_name, department_id, 限制部门id不是 80 50 20
-- 按照枚举 in 的方式来操作
-- not in(数据) 要求数据行内容指定字段数据不能满足 in 之后小括号数据要求
select employee_id, first_name, department_id
from t_employees
where department_id not in (20, 50, 80);
6.4.8 like 模糊查询
-- like
-- _ 匹配一个字符
-- % 匹配任意个数字符

-- 在员工表中查询,找出 employee_id, first_name, 要求名字中首字母为 D
-- D% 限制字段数据为 D 开头,后面字符不限制
select employee_id, first_name
from t_employees
where first_name like 'D%';

-- 在员工表中查询,找出 employee_id, first_name, 要求名字中首字母为 D, 并且名字字符个位为 5 个
-- D____ D 开头,后面是 4 个下划线,对应要求 D 开头,字符个数为 5
select employee_id, first_name
from t_employees
where first_name like 'D____';  

-- 在员工表中查询,找出 employee_id, first_name, 要求名字中包含 D
-- %D% 要求字段数据中包含 D 字符,其他无限制
select employee_id, first_name
from t_employees
where first_name like '%D%';
6.4.9 分支结构查询
-- case
--      when condition1 then ret1
--      when condition2 then ret2
--      when condition3 then ret3
-- end
-- 分支处理的数据结果,可以认为是一个临时数据字段,可以使用别名

-- 在员工表中查询,找出  employee_id, first_name, 同时工资按照条件进行等级划分, level
select employee_id,
       first_name,
       salary,
       case
           when salary >= 15000 then 'A'
           when salary >= 10000 then 'B'
           when salary >= 8000 then 'C'
           when salary > 5000 then 'D'
           else 'E'
           end as 'level' -- 利用别名给予当前 case end 分支查询结果字段名称
from t_employees;

-- 两个 SQL 执行结果一致,条件限制满足情况,可以不用后续 and 条件约束
select employee_id,
       first_name,
       salary,
       case
           when salary >= 15000 then 'A'
           when salary >= 10000 and salary < 15000 then 'B'
           when salary >= 8000 and salary < 10000 then 'C'
           when salary > 5000 and salary < 8000 then 'D'
           else 'E'
           end as 'level' -- 利用别名给予当前 case end 分支查询结果字段名称
from t_employees;
6.5 时间查询
select 时间函数([参数列表]);
-- 当前系统时间(年,月,日,时,分,秒)
select sysdate();
select current_timestamp();
select now();

-- 当前系统时间日期(年,月,日)
select curdate();
-- 当前系统时间(时,分,秒)
select curtime();

-- 获取指定日期是当前这一年的第几周
select week(curdate());
select week('2020-7-20');

-- 获取指定时间的是今天的第几个小时
select hour(sysdate());
-- 获取指定时间的是这一小时的第几分钟
select minute(sysdate());
-- 获取指定时间的是这一分钟的第几秒
select second(sysdate());
6.6 字符串应用
-- 拼接多个字符串
-- concat(str1, str2, str3...);
select concat('今天', '郑州', '天气不错~~~');

-- 指定字符串,指定下标位置开始,要求指定字符个数,使用新字符串替换
-- insert(oldStr, off, len, newStr);
-- 数据库字符串下标从 1 开始
select insert('0123456789', 0, 2, '郑州'); -- 字符串操作没有生效
select insert('0123456789', 1, 2, '郑州');
-- 字符串有效果!!!

-- 字符串数据内容转大写
select upper('abcdefg');
-- 字符串数据内容转小写
select lower('ABCDEFG');

-- 截取子字符串,参数是指定操作字符串,off 是指定下标位置开始, len 是计数字符串字符个数
-- substring(str, off, len);
select substring('0123456789', 0, 2); -- 字符串操作没有生效,字符串在数据库中下标从 1 开始
select substring('0123456789', 1, 2); -- 01
select substring('0123456789', 2, 2); -- 12
6.7 内置方法
-- 求员工表所有工资总和/每月固定人力成本
select sum(salary)
from t_employees;

-- 求员工表所有员工的平均工资
select avg(salary)
from t_employees;

-- 找出员工表最高工资
select max(salary)
from t_employees;

-- 找出员工表最低工资
select min(salary)
from t_employees;

-- 计数统计员工人数
-- 以员工 ID 为计数参照数据,统计当前员工表有多少员工
select count(employee_id)
from t_employees;

-- * 通配符,确定当前数据表中有多少数据行
select count(*)
from t_employees;

-- 1 在很多开发语言中表示 true (0 为 false)
-- count(1) 数据行存在,表示 1,同样可以统计当前数据表有多少行
select count(1)
from t_employees;

-- 统计员工中有多少人有提成比例
select count(commission_pct)
from t_employees;
6.8 分组查询
select fieldName -- 常见计数操作
from tbName
wherec condition
group by 分组条件;
-- 查询每一个部门的人数
-- 1. 按照员工表中 department_id 进行分组限制
-- 2. 计数统计需要使用 count,需要得到的是员工人数,计数字段 employee_id
select department_id, count(employee_id) -- 目标字段为部门 id 和 计数员工人数
from t_employees
group by department_id;
-- 分组条件为 department_id

-- 查询各部门的固定人力成本, 按照部门分组,每一个部门的固定工资总和
-- 1. 按照员工表中 department_id 进行分组限制
-- 2. 求工资总和 sum(salary)
select department_id, sum(salary)
from t_employees
group by department_id;

-- 查询各部门员工平均人力成本, 按照部门分组,每一个部门员工的平均
-- 1. 按照员工表中 department_id 进行分组限制
-- 2. 求平均工资 avg(salary)
select department_id, avg(salary)
from t_employees
group by department_id;

-- 查询各部门,各岗位的人数
-- 1. 首先按照 department_id 分组
-- 2. 然后按照 job_id 分组
-- 3. 计数员工人数 count(employee_id)
select department_id, job_id, count(employee_id)
from t_employees
group by department_id, job_id; -- group by 可以将目标分组字段一并完成,顺序为分组操作先后顺序
-- [42000][1055] Expression #1 of SELECT list is not in GROUP BY clause and contains 
-- nonaggregated column 'company.t_employees.department_id' which is not functionally 
-- dependent on columns in GROUP BY clause; this is incompatible with 
-- sql_mode=only_full_group_by
-- 【注意】分组操作实际上是二次查询,数据处理操作。是基于当前已查询结果为临时数据
-- group by 在临时数据之上进行分组操作,分组使用的字段数据必须是 select 之后的字段内容
select department_id
from t_employees
group by job_id;

-- select department_id, avg(salary)
-- from t_employees  -- SQL 语句执行到当前 from t_employees 已经和数据库表结构断开,
-- 分组是在查询结果之后完成
-- group by department_id; -- 分组条件是在 select 操作之后完成,需要使用 select 之后的字段数据
6.9 分组过滤查询
select fieldName
from tbName
where condition
group by 分组条件
having 分组之后的限定条件;
-- having 是在 group by 分组之后的条件限制关键字。
-- 找出指定部门编号在 100, 20, 50, 80 部门的员工最高工资
-- 1. 按照部门分组 department_id 分组条件
-- 2. 最高工资 max(salary)
-- 3. 限制部门 department_id 在 100, 20, 50, 80 数据以内 in

-- 方案 1 先分组,后限制
-- 先分组,再次限制,会有一些多余的,无用的条件进入分组操作,分组之后的判断
-- 数据较多,操作效率一般
select department_id, max(salary)
from t_employees
group by department_id
having department_id in (20, 50, 80, 100);

-- 方案 2 先限制,后分组
-- 明确部门限制,后期进行分组,所有操作的数据都是分组必须使用的内容
-- 数据量在分组之前较少,效率较高
select department_id, max(salary)
from t_employees
where department_id in (20, 50, 80, 100)
group by department_id;

-- 找出指定部门编号在 100, 20, 50, 80 部门的,同时要求员工的领导 manager_id = 100
-- 各部门最高工资
-- 1. 按照部门分组 department_id 分组条件
-- 2. 最高工资 max(salary)
-- 3. 限制员工信息要求 manager_id = 100
-- 4. 限制部门 department_id 在 100, 20, 50, 80 数据以内 in
select department_id, max(salary)
from t_employees
where manager_id = 100
group by department_id
having department_id in (20, 50, 80, 100);
6.10 限定查询
-- limit
-- 查询员工表信息,要求字段 employee_id, first_name
select employee_id, first_name
from t_employees;

-- 查询员工表信息,要求字段 employee_id, first_name,数据总行数为 5 行
select employee_id, first_name
from t_employees
limit 5;

-- 查询员工表信息,要求字段 employee_id, first_name
-- limit 0, 10 0 表示从下标 0 开始计数,数据行数 10 行
select employee_id, first_name
from t_employees
limit 0, 10;

-- limit 10, 10
-- 10 表示从下标 10 开始计数,数据行数 10 行
select employee_id, first_name
from t_employees
limit 10, 10;

-- limit offset, count;
-- 分页,当数据量较大的时候,给予用户数据内容,在页面中有单页数据量限制
-- 例如 一页有效数据 50 个,一共 10 页
-- 前端页面中 1, 2, 3, 4, 5
-- 格式总结: limit (pageCount - 1) * rowCount, rowCount;
-- pageCount 页码 rowCount 每一页多少行数据
-- 【项目中会完成】分页工具类
6.11 基本查询总结
select fieldName
from tbName
where condition_
group by 分组
having 分组过滤
order by 排序 [asc/desc]
limit offset, count;

-- select 查询指定的字段
-- from 数据来源,从那张表中查询数据
-- where 查询数据的条件
-- group by 分组
-- having 分组之后条件约束
-- order by 排序要求 asc升序
-- limit 限制结果行数
-- null 是否为空
-- distinct 去重
6.12 子查询
6.12.1 基本格式
-- select fieldName
-- from tbName
-- where (子查询)
6.12.2 子查询结果作为条件判断约束
-- 在员工表中查询,找出员工工资高于 Jack 的  employee_id, first_name
-- 1. 找出 Jack 的工资 --> 8400
-- 查询结果有且只有一个数据
select salary
from t_employees
where first_name = 'Jack';

-- 2. 找出 employee_id, first_name 要求工资高于 8400
select employee_id, first_name
from t_employees
where salary > 8400;

-- 整合为子查询形式
select employee_id, first_name
from t_employees
where salary > (select salary
                from t_employees
                where first_name = 'Jack');
6.12.2 子查询结果作为条件判断约束, 采用枚举方式 in
-- 找出和 David 同部门的员工
-- 1. 找出 David 部门数据
-- 查询结果为多个数据 -- department_id 60, 80
select distinct department_id
from t_employees
where first_name = 'David';

-- 2. 找出 60, 80 部门的其他员工
select employee_id, first_name, department_id
from t_employees
where department_id in (60, 80);

-- 合并子查询
select employee_id, first_name, department_id
from t_employees
where department_id in (select distinct department_id
                        from t_employees
                        where first_name = 'David');
6.12.3 子查询结果看作临时表,作为其他查询的数据来源
-- 找出工资前五的员工信息 employee_id, first_name, salary
-- 1. 按照工资排序
select employee_id, first_name, salary
from t_employees
order by salary desc;

-- 2. 以上排序 SQL 结果看作是一个临时表,查询数据
-- 【仅演示】语法特征,不作为开发操作必备条件
select employee_id, first_name
from (select employee_id, first_name
      from t_employees
      order by salary desc) as temp
limit 5;

-- 目前最好的解决方案,子查询少用!!!
select employee_id, first_name
from t_employees
order by salary desc
limit 5;
6.13 合并查询【仅了解】
-- union
-- 员工表中找出员工id 和 员工名字 从 国籍表找出国籍 ID 和 国家名称
select employee_id, first_name
from t_employees
union
select country_id, country_name
from t_countries;

-- 员工表中找出员工id  从 部门表找出部门 ID
-- union 合并查询,但是去重
select employee_id
from t_employees
union
select department_id
from t_departments;

-- union all 合并查询,但是不去重
select employee_id
from t_employees
union all
select department_id
from t_departments;
6.14 表连接查询【重点】

解决数据表多表查询操作,表与表之间员工存在相对于的数据约束关系,数据限制关系,数据联系。

例如:员工表中的部门 id 和 部门表中的 部门 id 字段数据一个是对应的。可以通过多表表连接查询获取员工名称(员工表),部门名称(部门表)

6.14.1 基本格式
select fieldName1, fieldName2
from tbName1
连接符 tbName2
on 条件;
6.14.2 笛卡尔乘积【避免】
-- 找出员工ID,员工名字和部门名字
-- 字段分析:
--      员工ID,员工名字 ==> 员工表
--      部门名称        ==> 部门表
-- 【结果错误】 因为没有任何的数据约束和限制,两个表查询目标字段数据一一匹配
-- 导致查询结果数据总行数 27 * 107 == 2889
select employee_id, first_name, department_name
from t_employees
         inner join t_departments;

select count(department_id)
from t_departments; -- 27 个部门
select count(employee_id)
from t_employees;
-- 107 个员工
6.14.3 内连接查询 inner join 两张表数据
-- 找出员工id,员工名字,部门名称数据
-- 字段分析:
--      employee_id,first_name ==> t_employees
--      department_name ==> t_departments
-- 【核心 条件约束/条件限制】
--      t_employees.department_id = t_departments.department_id
select employee_id, first_name, department_name
from t_employees
         inner join t_departments
                    on t_employees.department_id = t_departments.department_id;

# select employee_id, first_name, department_name
-- select 之后是目标查询的字段名称
# from t_employees
-- t_employees 员工表是 字段 employee_id, first_name 数据来源
#          inner join t_departments
-- inner join 连接符【内连接】 t_departments 部门表 字段 department_name 数据来源
#                     on t_employees.department_id = t_departments.department_id;
-- 限制的数据查询约束条件

-- 以上 SQL 优化
select employee_id, first_name, department_name
from t_employees te -- 员工表 t_employees 简称为 te
         inner join t_departments td -- 部门表 t_departments 简称为 td
                    on te.department_id = td.department_id;
6.14.4 内连接查询 inner join 三张表数据
-- 查询 employee_id, first_name, department_name, job_title
-- 字段分析
--      employee_id, first_name ==> t_employees
--      department_name         ==> t_departments
--      job_title               ==> t_jobs
-- 【核心 条件约束/条件限制】
--          t_employees.department_id = t_departments.department_id
--          t_employees.job_id = t_jobs.job_id
select employee_id, first_name, department_name, job_title
from t_employees te
         inner join t_departments td
                    on te.department_id = td.department_id
         inner join t_jobs tj
                    on te.job_id = tj.job_id;

-- 查询 employee_id, first_name, department_name, city
-- 字段分析
--      employee_id, first_name ==> t_employees
--      department_name         ==> t_departments
--      city                    ==> t_locations
-- 【核心 条件约束/条件限制】
--          t_employees.department_id = t_departments.department_id
--          t_departments.location_id = t_locations.location_id
select employee_id, first_name, department_name, city
from t_employees te
         inner join t_departments td
                    on te.department_id = td.department_id
         inner join t_locations tl
                    on td.location_id = tl.location_id;
6.14.5 内连接查询 inner join 四张表数据
-- 查询 employee_id, first_name, department_name, job_title, city
select employee_id, first_name, department_name, job_title, city
from t_employees te
         inner join t_departments td
                    on te.department_id = td.department_id
         inner join t_jobs tj
                    on te.job_id = tj.job_id
         inner join t_locations tl
                    on td.location_id = tl.location_id;

-- 查询 employee_id, first_name, department_name, city, country_name
select employee_id, first_name, department_name, city, country_name
from t_employees te
         inner join t_departments td
                    on te.department_id = td.department_id
         inner join t_locations tl
                    on td.location_id = tl.location_id
         inner join t_countries tc
                    on tl.country_id = tc.country_id;
6.14.6 内连接查询 inner join 五张表数据
-- 查询 employee_id, first_name, department_name, job_title, city, country_name
select employee_id, first_name, department_name, job_title, city, country_name
from t_employees te
         inner join t_departments td
                    on te.department_id = td.department_id
         inner join t_locations tl
                    on td.location_id = tl.location_id
         inner join t_jobs tj
                    on te.job_id = tj.job_id
         inner join t_countries tc
                    on tl.country_id = tc.country_id;
6.14.7 左外连接查询
-- 左外连接查询 连接符 left outer join
-- 查询字段数据如果为左表数据,字段数据完整展示
-- 查找字段数据如果为右表数据,匹配展示,如果没有对应数据内容显示 null
-- 部门表中一共有 27 个部门
select department_name
from t_departments;

-- 员工表中实际的部门个数
select count(distinct department_id)
from t_employees;

-- 查询所有部门名称,对应的员工信息,如果该部门没有员工,显示 null
-- 左表是部门表,右表是员工表
-- 左表 在 连接符 left outer join 左侧表
-- 右表 在 连接符 left outer join 右侧表
select department_name, employee_id, first_name
from t_departments td
         left outer join t_employees te
                         on td.department_id = te.department_id;

-- 查询各部门名称和对应员工人数,并且按照员工人数降序排序
select department_name, count(employee_id)
from t_departments td
         left outer join t_employees te
                         on td.department_id = te.department_id
group by department_name
order by count(employee_id) desc;

-- 查询各部门名称和对应员工人数,仅保留人数大于 20 的
select department_name, count(employee_id)
from t_departments td
         left outer join t_employees te
                         on td.department_id = te.department_id
group by department_name
having count(employee_id) > 20;
6.14.8 右外连接查询
-- 右外连接查询 连接符 right outer join
-- 查询字段数据如果为右表数据,字段数据完整展示
-- 查找字段数据如果为左表数据,匹配展示,如果没有对应数据内容显示 null

-- 查询所有部门名称,对应的员工信息,如果该部门没有员工,显示 null
-- 右表是部门表,左表是员工表
-- 左表 在 连接符 right outer join 左侧表
-- 右表 在 连接符 right outer join 右侧表
select department_name, employee_id, first_name
from t_employees te
         right outer join t_departments td
                         on td.department_id = te.department_id;
7. DML 语句

数据表创建操作,数据行插入,数据修改,数据删除

7.1 创建数据表

create table tbName (fieldName fieldType 数据约束方式 注释)

create table person
(
    -- id 是字段名称,int 为数据类型 ==> Java 中的 int/Integer
    id     int comment '人员id',
    -- name 是字段名称,varchar 为数据类型,可变长字符串,节省空间,效率较低
    -- 32 表示当前字符串最大支持字符个数 32 个。 ==> Java 中的 String
    name   varchar(32) comment '人员姓名',
    -- age 为字段名称,int 为数据类型 ==> Java 中的 int/Integer
    age    int comment '人员年龄',
    -- gender 为字段名称, tinyint 为数据类型,数据类型等价于 Java 中的 byte/boolean
    -- tinyint(1) 表示当前数值数字个数有且只有一位,限制之后对应 Java boolean
    gender tinyint(1) comment '人员性别',
    -- salary 为字段名称,float(8, 2) 单精度浮点类型,8 表示有效数据为为 8 为,2表示
    -- 保留两位小数,当前数据的范围 -999999.99 ~ 999999.99
    salary float(8, 2) comment '人员工资'
);

-- 展示当前 person 表数据结构
desc person;

# +--------+-------------+------+-----+---------+-------+
# | Field  | Type        | Null | Key | Default | Extra |
# +--------+-------------+------+-----+---------+-------+
# | id     | int(11)     | YES  |     | NULL    |       |
# | name   | varchar(32) | YES  |     | NULL    |       |
# | age    | int(11)     | YES  |     | NULL    |       |
# | gender | tinyint(1)  | YES  |     | NULL    |       |
# | salary | float(8,2)  | YES  |     | NULL    |       |
# +--------+-------------+------+-----+---------+-------+

-- 展示当前选择数据库中有多少数据表
show tables;
7.2 insert 数据插入操作
-- 完整模式
-- 明确所有的字段名称,明确所有字段名对应数据
-- person(id, name, age, gender, salary) 明确添加数据操作对应的数据表示是哪一个
-- values (1, '苟磊', 16, 0, 10.56) 要求和字段一一对应,类似于 Java 方法的实际参数
-- 类型一致,顺序一致,个数一致
insert into person(id, name, age, gender, salary)
values (1, '苟磊', 16, 0, 10.56);

-- 查询数据
select *
from person;

-- 简版模式
-- 指定字段名称,指定赋值数据
-- person(id, name) 指定添加数据表为 person 表,目标操作添加字段 id name
-- values (2, '2218的ADC') 对应当前字段数据内容,类型一致,顺序一致,个数一致
-- 其他未赋值的字段数据,采用数据表设计过程中对应的默认值,当前默认值为 null,无数据
insert into person(id, name)
values (2, '2218的ADC');

-- 字段指定无顺序要求,任意可行,唯一要求是字段顺序和 values 中提供的数据类型一致,顺序一致,个数一致
insert into person(name, age, salary)
values ('子轩', 20, 450);

-- 添加操作数据存在重复性,不是修改原本的数据行,而且新数据
insert into person(id, name)
values (2, '2218的ADC');

-- 极简模式
-- 未声明指定字段名称,要求 values 数据顺序,数据类型,数据个数必须和当前数据表
-- 所有字段一一对应
insert into person
values (3, '万峰', 25, 0, 10000.50);
insert into person
values (5, '子鹏', 25, 0, 10005.20);
7.3 update 数据修改【慎用】
-- Unsafe query: 'Update' statement without 'where' updates all table rows at once
-- 不安全的 SQL 语句: update 操作在没有 where 条件约束的情况下,会更新数据表中的所有数据行。
-- 【注意】更新操作必须有添加数据,如果没有,不要用!!!
update person
set name = '子鹏说自己32岁';

-- Query OK, 1 row affected in 5 ms
update person -- 明确修改数据表是哪一个
set name = '子鹏说自己32岁' -- set 之后是目标字段名称和对应数据
where id = 5;
-- 条件约束,限制哪些数据行可以修改指定字段数据

-- 可以同时修改多个字段,字段数据修改使用逗号隔开
update person
set name   = '万峰不是很高兴,感觉子鹏欺骗了他',
    age    = 23,
    salary = 500
where id = 3;

-- 通过条件约束,批量修改数据行数据
update person
set salary = 100000.5
where id < 5;
7.4 delete 数据删除【慎用】
-- Unsafe query: 'Delete' statement without 'where' clears all data in the table
-- 不安全的 SQL 语句: Delete 操作没有 where 条件限制会清空数据表中的所有数据行
delete
from person;

-- 指定条件删除允许
delete
from person -- 删除哪一个数据表中的数据
where id = 3; -- 约束条件
7.5 truncate 操作清空整表数据
-- 清空整个数据表所有数据行内容,并且会影响到一部分的数据约束/数据操作
truncate table person; 
8. 数据类型
8.1 数值类型

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aF6LLZ1W-1680436436520)(img/04-MySQL数值类型.png)]

8.2 日期类型【小重点】

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Bn1pORVl-1680436436520)(img/05-MySQL日期和时间类型.png)]

8.3 字符串类型

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sZJKCUMH-1680436436521)(img/06-MySQL字符串类型.png)]

char(n) 和 varchar(n) 中括号中 n 代表字符的个数,并不代表字节个数,比如 CHAR(30) 就可以存储 30 个字符。

CHAR 和 VARCHAR 类型类似,但它们保存和检索的方式不同。它们的最大长度和是否尾部空格被保留等方面也不同。在存储或检索过程中不进行大小写转换。

BINARY 和 VARBINARY 类似于 CHAR 和 VARCHAR,不同的是它们包含二进制字符串而不要非二进制字符串。也就是说,它们包含字节字符串而不是字符字符串。这说明它们没有字符集,并且排序和比较基于列值字节的数值值。

BLOB 是一个二进制大对象,可以容纳可变数量的数据。有 4 种 BLOB 类型:TINYBLOB、BLOB、MEDIUMBLOB 和 LONGBLOB。它们区别在于可容纳存储范围不同。

有 4 种 TEXT 类型:TINYTEXT、TEXT、MEDIUMTEXT 和 LONGTEXT。对应的这 4 种 BLOB 类型,可存储的最大长度不同,可根据实际情况选择。

9. 数据约束【重点】
9.1 default 默认值
-- 数据表中指定字段,在没有赋值的情况下,采用默认数据给予赋值操作
create table student1
(
    id      int comment '学生ID',
    name    varchar(32) comment '学生姓名',
    country varchar(32) default 'PRC' comment '学生国籍'
);

desc student1;
-- 插入数据测试效果
-- country 字段数据对应当前数据行插入操作,直接选择默认值 'PRC' 使用
insert into student1(id, name)
VALUES (1, '苟磊');

-- 插入数据操作,直接指定默认修饰字段数据,数据内容选择当前条件操作
insert into student1(id, name, country)
values (2, '子鹏', '中国');

select *
from student1;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CkZJbmfk-1680436436521)(img/07-数据约束default默认值.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wJowMWKs-1680436436522)(img/08-数据约束default默认值数据插入效果.png)]

9.2 not null 非空
-- 限制数据表中的字段不可以为 null,不可以为空
-- 部分软件中的简拼 NN
create table student2
(
    id      int not null comment '学生id,非空约束',
    name    varchar(32) comment '学生姓名',
    country varchar(32) default 'PRC' comment '学生国籍'
);

desc student2;
-- 插入数据演示
-- id 非空字段有对应的数据,未触发语法错误,同时国籍有默认值
insert into student2(id, name)
VALUES (1, '苟磊');

-- 有且只给 id 字段赋值,其他字段数据情况
-- name 为 null 空值,国籍使用默认值数据赋值
insert into student2(id)
values (2);

-- Error [1364] Field 'id' doesn't have a default value
-- 语法错误,id 字段没有默认值,且没有赋值操作,当前 id 数据约束为非空
insert into student2(name)
values ('张三');

select *
from student2;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b0LgL5W1-1680436436522)(img/09-数据约束not null非空约束.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-etGUViBZ-1680436436523)(img/10-数据约束not null非空约束数据添加效果.png)]

9.3 unique 唯一
-- 唯一约束字段,要求当前数据不能重复。表中所有数据行数据唯一。
create table student3
(
    id      int unique comment '学生id,唯一约束,不可重复',
    name    varchar(32) not null comment '学生姓名,不可以为空',
    country varchar(32) default 'PRC' comment '学生国籍,默认值 PRC'
);

desc student3;

-- 插入数据演示
insert into student3(id, name)
values (1, '苟磊');

-- 插入 id 重复的数据
-- Error [23000][1062] Duplicate entry '1' for key 'id'
-- unique 唯一约束字段 id 数据重复,1 数据重复
insert into student3(id, name)
values (1, '张三');

-- 插入数据没有给予唯一约束字段 id 赋值操作
-- id 字段数据为 null 空值
insert into student3(name)
values ('张三');

-- 数据库数据行数据 null 空值不作为唯一判断
insert into student3(name)
values ('李四');

select *
from student3;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UGEpXdpn-1680436436523)(img/11-数据约束unique唯一限制.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GW7Sq252-1680436436524)(img/12-数据约束unique唯一限制数据情况.png)]

9.4 primary key 主键
-- 唯一 + 非空
-- 字段数据在数据行中不可以重复,同时要求字段不可以为 null 空值
-- 主键字段一般是开发中数据行的唯一参考数据字段,通常不会用带有业务逻辑的字段数据作为主键
-- 以下字段不适合作为主键 例如: 性别,年龄,身高,体重....
create table student4
(
    id      int primary key comment '学生id,主键修饰,PRI',
    name    varchar(32) not null comment '学生姓名,非空修饰',
    country varchar(32) default 'PRC'
);

desc student4;

-- 插入数据
insert into student4(id, name)
values (1, '苟磊');

-- 没有给予 ID 数据,ID 字段主键修饰,要求【非空】,当前情况下没有给予默认值约束
-- 语法错误!!!
-- Error [HY000][1364] Field 'id' doesn't have a default value
insert into student4(name)
values ('张三');

-- ID 字段主键约束,要求【唯一】,数据行中已经存储 id = 1 的数据,数据不可以重复
-- Error [23000][1062] Duplicate entry '1' for key 'PRIMARY'
insert into student4(id, name)
values (1, '张三');

select *
from student4;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xH4YJNtx-1680436436524)(img/13-数据约束primary key主键约束.png)]

9.5 auto_increment 自增长
-- 自增长数据添加的过程中,自动累加,自动赋值
-- 【要求】 auto_increment 自增长修饰数据必须一个 Key 而且通常是 PRI 主键修饰
create table student5
(
    id      int primary key auto_increment comment '学生id,主键修饰,自增长约束',
    name    varchar(32) not null comment '学生姓名,非空约束',
    country varchar(32) default 'PRC' comment '国籍信息,默认值 PRC'
);

desc student5;

-- 自增长数据,默认从 1 开始,随着数据的添加,自增加数据自动累加
insert into student5(name)
values ('郭德纲'); -- id 1
insert into student5(name)
values ('于谦'); -- id 2

-- 自增长数据字段,如果在添加过程中,对于当前字段添加数据内容,超出原本的自增长累加数据
-- 会影响当前自增长情况,从添加数据位置开始继续累加
-- 指定 id = 5 超出原本的自增长(3)数据情况,之后的 id 数据在没有赋值的情况下从 6 开始
insert into student5(id, name)
values (5, '高峰'); -- id 5
insert into student5(name)
values ('栾云平'); -- id 6

-- 自增长字段数据赋值情况小于当前自增长累加数据,对于自增长累加没有任何影响,数据延续之前的累加
-- 计数数据方式
insert into student5(id, name)
values (3, '郭麒麟'); -- id 3
insert into student5(name)
values ('阎鹤祥'); -- id 7 8 执行两次

-- 删除 id 为 8 的数据
delete
from student5
where id = 8;

-- 自增长数据 delete 删除之前的数据内容,对于自增长数据的累加没有影响
insert into student5(name)
values ('岳云鹏'); -- id 9
insert into student5(name)
values ('孙越'); -- id 10

-- 已删除数据字段,可以重新放入
insert into student5(id, name)
values (8, '张云雷'); -- id 8
insert into student5(name)
values ('杨九郎'); -- id 11

-- 清空整表数据
-- truncate 操作在清空数据的情况下,同时对自增长数据进行重置!
truncate student5;

insert into student5(name)
values ('郭德纲'); -- id 1

select *
from student5;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eIIZaQ4E-1680436436525)(img/14-数据约束auto_increment自增长.png)]

9.6 外键约束
create table employee
(
    id              int primary key auto_increment comment '员工id,主键自增长约束',
    name            varchar(32) not null comment '员工名称,非空约束',
    department_name varchar(32) not null comment '部门名称,非空约束'
);

desc employee;

-- 给予当前数据表内容插入数据操作
insert into employee(name, department_name)
VALUES ('张三', '销售部');
insert into employee(name, department_name)
VALUES ('李四', '销售部');
insert into employee(name, department_name)
VALUES ('王五', '销售部');
insert into employee(name, department_name)
VALUES ('赵六', '销售部');
insert into employee(name, department_name)
VALUES ('周七', '销售部');
insert into employee(name, department_name)
VALUES ('苟磊', 'Java学科部');
insert into employee(name, department_name)
VALUES ('老黑', 'Java学科部');
insert into employee(name, department_name)
VALUES ('强哥', 'Java学科部');
insert into employee(name, department_name)
VALUES ('鸽姐', '品质保障部');
insert into employee(name, department_name)
VALUES ('萍姐', '品质保障部');
insert into employee(name, department_name)
VALUES ('丽姐', '品质保障部');
insert into employee(name, department_name)
VALUES ('小王姐', '品质保障部');

select *
from employee;

-- 问题
--  1. 部门信息数据冗余,导致数据浪费
--  2. 数据行信息不具备【原子性 不可拆分】,数据行内容可以分为【员工信息】和【部门信息】
-- 删除当前的 employee

drop table employee;

-- 重新设计数据表
-- 部门表
create table department
(
    department_id   int primary key auto_increment comment '部门id,主键自增长修饰',
    department_name varchar(32) not null comment '部门名称,非空修饰'
);

-- 员工表
create table employee
(
    id            int primary key auto_increment comment '员工id,主键自增长修饰',
    name          varchar(32) not null comment '员工名字,非空修饰',
    department_id int         not null comment '部门id,,非空修饰'
);

desc department;
desc employee;

-- 插入数据
-- 首先插入部门数据
insert into department(department_name)
values ('销售部');
insert into department(department_name)
values ('Java学科部');
insert into department(department_name)
values ('品质保障部');

select *
from department;

-- 插入员工数据
insert into employee(name, department_id)
VALUES ('张三', 1);
insert into employee(name, department_id)
VALUES ('李四', 1);
insert into employee(name, department_id)
VALUES ('王五', 1);
insert into employee(name, department_id)
VALUES ('赵六', 1);
insert into employee(name, department_id)
VALUES ('周七', 1);
insert into employee(name, department_id)
VALUES ('苟磊', 2);
insert into employee(name, department_id)
VALUES ('老黑', 2);
insert into employee(name, department_id)
VALUES ('强哥', 2);
insert into employee(name, department_id)
VALUES ('鸽姐', 3);
insert into employee(name, department_id)
VALUES ('萍姐', 3);
insert into employee(name, department_id)
VALUES ('丽姐', 3);
insert into employee(name, department_id)
VALUES ('小王姐', 3);

select *
from employee;

-- 联表查询找到字段数据
select id, name, department_name
from employee
         inner join department d on employee.department_id = d.department_id;

-- 当前员工表添加数据是允许放入的
-- 【期望】不应该存储,因为当前添加使用的部门 id 数据不存在。
--  部门表数据可以约束员工表数据操作。
insert into employee(name, department_id)
values ('玉杰', 5);

-- 删除当前部门 id 为 5 员工表数据
delete
from employee
where department_id = 5;

-- 添加外键约束声明
-- 员工表中的 department_id 字段和部门表中的 department_id 【外键约束】
-- 【外键约束】 当前表字段被其他表字段数据约束
alter table employee -- 修改数据表
    add constraint fk_emp_dept -- add 添加 constraint 声明 fk_emp_dept 外键名称
        foreign key (department_id) -- 当前 employee 表中 department_id 外键字段
            references department (department_id);  -- 外键链接的目标表(目标字段)

-- Error [23000][1452] Cannot add or update a child row: a foreign key constraint fails 
-- (`javaee_2218`.`employee`, CONSTRAINT `fk_emp_dept` FOREIGN KEY (`department_id`) 
-- REFERENCES `department` (`department_id`))
-- 无法添加和修改一个子表/从表数据行,因为存在外键约束,子表添加过程中,受到外键约束字段会在主表中进行数据判断之
-- 后才可以添加 
-- department_id = 5 在 部门中不存在数据行信息
insert into employee(name, department_id)
values ('玉杰', 5);
9.7 外键约束级联操作
-- 外键约束优缺点
-- 优点:
--      1. 规范从表/子表数据添加操作。外键约束字段有且只能在主表约束数据范围以内操作
--      2. 主表在修改/删除字段过程中,限制主表操作,不能直接删除/修改,首先要考虑子表/从表数据使用问题

-- Error[23000][1451] Cannot delete or update a parent row: a foreign key constraint fails
-- (`javaee_2218`.`employee`, CONSTRAINT `fk_emp_dept` FOREIGN KEY (`department_id`)
-- REFERENCES `department` (`department_id`))
-- 删除/修改主表字段,对应从表外键约束还在使用主表字段数据内容,无法直接修改/删除
delete
from department
where department_id = 1;

-- 缺点:
--      1. 从表/子表操作确实非常规范,安全,但是对于 MySQL 性能压力较大
--      2. 主表操作繁琐,不便。
--      3. 使用外键约束,会导致数据表耦合度过高,不方便操作。

-- 【使用建议】
-- 数据表设计可以考虑存在外键约束思想,但是不要引入外键,关于外键的功能可以通过其他操作实现。

-- MySQL 针对于外键约束之后,主表操作繁琐,不便,优化了【级联操作】
-- 主表字段修改,从表随之修改【级联修改】
-- 主表字段删除,从表使用主表字段信息的数据行同步删除【级联删除】

-- 删除原外键约束
alter table employee
    drop foreign key fk_emp_dept;

-- 添加外键约束,同步加入级联删除和级联修改
alter table employee -- 修改数据表
    add constraint fk_emp_dept -- add 添加 constraint 声明 fk_emp_dept 外键名称
        foreign key (department_id) -- 当前 employee 表中 department_id 外键字段
            references department (department_id) -- 外键链接的目标表(目标字段)
            on delete cascade -- 加入【级联删除】
            on update cascade; -- 加入【级联修改】

select *
from employee;

-- 级联修改效果
-- 修改主表外键约束提供限制的字段数据,
-- 原本 department_id = 3 ==> department_id = 5
update department
set department_id = 5
where department_id = 3;

-- 从表数据情况
-- 从表原本 department_id 为 3 的数据同步修改为 5 【级联修改】
select *
from employee;

-- 级联删除效果
-- 删除主表 department_id = 1 的数据内容
delete
from department
where department_id = 1;

-- 从表数据情况
-- 从表原本 department_id 为 1 数据表同步删除【级联删除】
select *
from employee;
10. 事务操作 DTL

更新数据操作(insert delete update)操作有可能会导致数据库,数据表数据内容损坏或者丢失。

游戏打 BOSS 游戏存储点。SavePoint

10.1 相关 SQL 语句
# 开启事务操作,关闭自动提交
# 自动提交 SQL 操作默认情况下,所有 SQL 语句一旦执行,对数据表数据内容直接更新、
# 关闭自动提交,假更新/缓冲更新,数据的所有效果都是临时的,仅限于当前事物操作范围以内,其他用户看到数据无变化
set autocommit = 0;

# 回滚,数据回滚到 set autocommit = 0; 之后 或者 commit 之后
rollback;

# 提交SQL ,提交  set autocommit = 0; 之后 或者 rollback; 之后的 SQL 语句
# 事务中的所有 SQL 语句提交
# 【注意】 commit 不会关闭事务操作,不会开启自动提交。
commit;

# 关闭事务操作,开启自动提交
# 自动将事务操作中没有 commit 所有 SQL 语句自动提交
set autocommit = 1;
 3. 使用外键约束,会导致数据表耦合度过高,不方便操作。

– 【使用建议】
– 数据表设计可以考虑存在外键约束思想,但是不要引入外键,关于外键的功能可以通过其他操作实现。

– MySQL 针对于外键约束之后,主表操作繁琐,不便,优化了【级联操作】
– 主表字段修改,从表随之修改【级联修改】
– 主表字段删除,从表使用主表字段信息的数据行同步删除【级联删除】

– 删除原外键约束
alter table employee
drop foreign key fk_emp_dept;

– 添加外键约束,同步加入级联删除和级联修改
alter table employee – 修改数据表
add constraint fk_emp_dept – add 添加 constraint 声明 fk_emp_dept 外键名称
foreign key (department_id) – 当前 employee 表中 department_id 外键字段
references department (department_id) – 外键链接的目标表(目标字段)
on delete cascade – 加入【级联删除】
on update cascade; – 加入【级联修改】

select *
from employee;

– 级联修改效果
– 修改主表外键约束提供限制的字段数据,
– 原本 department_id = 3 ==> department_id = 5
update department
set department_id = 5
where department_id = 3;

– 从表数据情况
– 从表原本 department_id 为 3 的数据同步修改为 5 【级联修改】
select *
from employee;

– 级联删除效果
– 删除主表 department_id = 1 的数据内容
delete
from department
where department_id = 1;

– 从表数据情况
– 从表原本 department_id 为 1 数据表同步删除【级联删除】
select *
from employee;


#### 10. 事务操作 DTL

> 更新数据操作(insert delete update)操作有可能会导致数据库,数据表数据内容损坏或者丢失。
>
> 游戏打 BOSS 游戏存储点。SavePoint

##### 10.1 相关 SQL 语句

```mysql
# 开启事务操作,关闭自动提交
# 自动提交 SQL 操作默认情况下,所有 SQL 语句一旦执行,对数据表数据内容直接更新、
# 关闭自动提交,假更新/缓冲更新,数据的所有效果都是临时的,仅限于当前事物操作范围以内,其他用户看到数据无变化
set autocommit = 0;

# 回滚,数据回滚到 set autocommit = 0; 之后 或者 commit 之后
rollback;

# 提交SQL ,提交  set autocommit = 0; 之后 或者 rollback; 之后的 SQL 语句
# 事务中的所有 SQL 语句提交
# 【注意】 commit 不会关闭事务操作,不会开启自动提交。
commit;

# 关闭事务操作,开启自动提交
# 自动将事务操作中没有 commit 所有 SQL 语句自动提交
set autocommit = 1;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值