多表查询、事务、DCL


Posted in MySQL onApril 05, 2021

一、多表查询
查询语法:

select 
	列名列表
from
	表名列表
where ...

代码示例:

# 创建部门表
CREATE TABLE dept2(
	id INT PRIMARY KEY AUTO_INCREMENT,
	NAME VARCHAR(20)
);
INSERT INTO dept2 (NAME) VALUES('开发部'),('市场部'),('财务部');
# 创建员工表
CREATE TABLE emp2(
	id INT PRIMARY KEY AUTO_INCREMENT,
	NAME VARCHAR(10),
	gender CHAR(1), -- 性别
	salary DOUBLE, -- 工资
	join_date DATE, -- 入职日期
	dept2_id INT,
	FOREIGN KEY (dept2_id) REFERENCES dept2(id) -- 外键,关联部门表(部门表的主键)
);
INSERT INTO emp2(NAME,gender,salary,join_date,dept2_id) VALUES('孙悟空','男',7200,'2013-02-24',1);
INSERT INTO emp2(NAME,gender,salary,join_date,dept2_id) VALUES('猪八戒','男',3600,'2010-12-02',2);
INSERT INTO emp2(NAME,gender,salary,join_date,dept2_id) VALUES('唐僧','男',9000,'2008-08-08',2);
INSERT INTO emp2(NAME,gender,salary,join_date,dept2_id) VALUES('白骨精','女',5000,'2015-10-07',3);
INSERT INTO emp2(NAME,gender,salary,join_date,dept2_id) VALUES('蜘蛛精','女',4500,'2011-03-14',1);
SELECT * FROM emp2,dept2; -- 多表查询
-- 笛卡尔积,会出现数据冗余

多表查询、事务、DCL

  • 笛卡尔积:取两个集合的所有组成情况。要完成多表查询,需要消除无用的数据。
  • 多表查询的分类
    参考链接:https://blog.csdn.net/qq_38125058/article/details/79946850
    • 1.内连接查询
      • (1)隐式内连接:使用where条件消除无用数据。
        例子:
-- 查询员工表的名称,性别,部门表的名称,第一种方法
SELECT emp2.`name`,emp2.`gender`,dept2.`name` FROM emp2,dept2 WHERE emp2.`dept2_id` = dept2.`id`;
-- 第二种方法
SELECT 
	t1.`name`,
	t1.`gender`,
	t2.`name`
FROM
	emp2 t1,dept2 t2
WHERE 
	t1.`dept2_id` = t2.`id`;

多表查询、事务、DCL

  • (2)显示内连接:
    语法:select 字段列表 from 表名1 [inner] join 表名2 on 条件
    代码示例:
SELECT * FROM emp2 INNER JOIN dept2 ON emp2.`dept2_id` = dept2.`id`;
SELECT * FROM emp2 JOIN dept2 ON emp2.`dept2_id` = dept2.`id`;

多表查询、事务、DCL
(3)内连接查询
a.从哪些表中查询数据
b.条件是什么
c.查询哪些字段

  • 2.外连接查询
    (1)左外连接
    语法:select 字段列表 from 表1 left [outer] join 表2 on 条件;
    查询的是左表所有数据以及其交集部分。
    (2)右外连接
    语法:select 字段列表 from 表1 right [outer] join 表2 on 条件;
    查询的是右表所有数据以及其交集部分。
SELECT * FROM dept2;
SELECT * FROM emp2;

-- 查询所有员工信息,如果员工有部门,则b们名称查询部门名称,没有部门,则不显示
SELECT 
	t1.*,t2.`name`
FROM 
	emp2 t1,dept2 t2
WHERE
	t1.`dept2_id` = t2.`id`;

-- emp2是左表,dept2是右表
SELECT t1.*,t2.`name` FROM emp2 t1 LEFT JOIN dept2 t2 ON t1.`dept2_id` = t2.`id`;

SELECT t1.*,t2.`name` FROM emp2 t1 RIGHT JOIN dept2 t2 ON t1.`dept2_id` = t2.`id`;
SELECT * FROM dept t2 RIGHT JOIN emp2 t1 ON t1.`dept2_id` = t2.`id`;

多表查询、事务、DCL
多表查询、事务、DCL
多表查询、事务、DCL
多表查询、事务、DCL
多表查询、事务、DCL
多表查询、事务、DCL

  • 3.子查询
    (1)概念:查询中嵌套查询,称嵌套查询为子查询。
-- 查询工资最高的员工信息
-- 1 查询最高的工资是多少 9000
SELECT MAX(salary) FROM emp2;
-- 2 查询员工信息,并且工资等于9000的
SELECT * FROM emp2 WHERE emp2.`salary` = 9000;

-- 一条SQL语句就完成查询工资最高的员工的信息,子查询
SELECT * FROM emp2 WHERE emp2.`salary` = (SELECT MAX(salary) FROM emp2);

多表查询、事务、DCL
多表查询、事务、DCL
多表查询、事务、DCL
(2)子查询的不同情况1–子查询的结果是单行单列的

  • 子查询可以作为条件,使用运算符去判断。运算符:> >= < <= =
-- 查询员工工资小于平均工资的人
SELECT AVG(salary) FROM emp2;
SELECT * FROM emp2 WHERE emp2.`salary` < (SELECT AVG(salary) FROM emp2);

多表查询、事务、DCL
多表查询、事务、DCL
(3)子查询的不同情况2–子查询的结果是多行单列的

-- 查询财务部的所有员工信息
SELECT id FROM dept2 WHERE NAME = '财务部';
SELECT * FROM emp2 WHERE dept2_id = 3;
-- 查询财务部和市场部的所有员工信息
SELECT id FROM dept2 WHERE NAME = '财务部' OR NAME = '市场部';
SELECT * FROM emp2 WHERE dept2_id = 3 OR dept2_id = 2; 
-- 简化写法,子查询, 查询财务部和市场部的所有员工信息
SELECT * FROM emp2 WHERE dept2_id IN (3,2);
SELECT * FROM emp2 WHERE dept2_id IN (SELECT id FROM dept2 WHERE NAME = '财务部' OR NAME = '市场部');

多表查询、事务、DCL
多表查询、事务、DCL
多表查询、事务、DCL
多表查询、事务、DCL
多表查询、事务、DCL
多表查询、事务、DCL
(4)子查询的不同情况2–子查询的结果是多行多列的

  • 子查询可以作为一张虚拟表参与查询
-- 多行
-- 查询员工入职日期是2011-11-11之后的员工信息和部门信息
-- 方法1,子查询
SELECT * FROM dept2 t1, (SELECT * FROM emp2 WHERE emp2.`join_date` > '2011-11-11') t2 WHERE t1.`id` = t2.dept2_id;

-- 方法2
SELECT * FROM emp2 WHERE emp2.`join_date` > '2011-11-11';

-- 普通内连接
-- 查询所有员工和部门信息
SELECT * FROM emp2 t1,dept2 t2 WHERE t1.`dept2_id` = t2.`id`;
-- 查询员工入职日期是2011-11-11之后的员工信息和部门信息
SELECT * FROM emp2 t1,dept2 t2 WHERE t1.`dept2_id` = t2.`id` AND t1.`join_date` > '2011-11-11';

多表查询、事务、DCL
多表查询、事务、DCL
多表查询、事务、DCL
多表查询、事务、DCL

二、事务
1.事务的基本介绍

  • (1)基本概念
    如果一个包含多个步骤的业务操作,被事务管理,那么这些操作要么同时成功,要么同时失败。
  • (2)操作
    • 开启事务:start transaction;
    • 回滚:rollback;
    • 提交:commit;
      多表查询、事务、DCL
      多表查询、事务、DCL
      多表查询、事务、DCL
      多表查询、事务、DCL
      多表查询、事务、DCL
      多表查询、事务、DCL
      多表查询、事务、DCL
      第一个窗口代码:
USE db3;
SELECT DATABASE();

CREATE TABLE account(
	id INT PRIMARY KEY AUTO_INCREMENT,
	NAME VARCHAR(10),
	balance DOUBLE
);
-- 添加数据
INSERT INTO account (NAME,balance) VALUES ('zhangsan',1000), ('lisi',1000);
SELECT * FROM account; -- 用于查看临时的数据状态
UPDATE account SET balance = 1000;
-- 张三给李四转账500元
-- 0. 开启事务
START TRANSACTION;
-- 1. 张三账户 -500
UPDATE account SET balance  = balance - 500 WHERE NAME = 'zhangsan';
-- 2. 李四账户 +500
-- 出错时,这个窗口会产生临时数据,也就是张三已经-500,李四已经+500,
-- 但是新打开一个询问窗口查看时,两个人钱数没变
-- 出错了
UPDATE account SET balance  = balance + 500 WHERE NAME = 'lisi';
-- 发现执行没有问题,提交事务
-- 提交事务后,打开另一个命令编辑窗口,数据都会发生变化
-- 如果不执行commit,则打开另一个命令编辑窗口,数据不会发生变化
COMMIT;
-- 发现出问题了,回滚事务
-- 此时如果一个步骤出问题,也不会产生临时钱数改变的数据
ROLLBACK;

另一个窗口代码:

SELECT * FROM account;
USE db3;
SELECT DATABASE();
  • (3)MySQL数据库中事务默认自动提交
    • 事务提交的两种方式:
      • 自动提交:
        • MySQL就是自动提交的
        • 一条DML(增删改)语句会自动提交一次事务。
      • 手动提交:
        • Oracle数据库默认是手动提交事务。
        • 需要先开启事务,再提交。
    • 修改事务的默认提交方式:
      • 查看事务的默认提交方式:SELECT @@autocommit; -- 1 代表自动提交,0 代表手动提交
      • 修改默认提交方式:SET @@autocommit=0;

代码:

-- 查看默认提交方式
-- 1 代表自动提交,0 代表手动提交
SELECT @@autocommit;
-- 修改为手动提交
SET @@autocommit=0;
UPDATE account SET balance = 30;
-- 手动提交时,如果不执行commit,重新打开窗口不会生效
COMMIT;

2.事务的四大特征
(1)原子性:是不可分割的最小操作单位,要么同时成功,要么同时失败。
(2)持久性:当事务提交或回滚后,数据会持久化的保存数据。
(3)隔离性:多个事务之间,相互独立。
(4)一致性:事务操作前后,数据总量不变。(比如转账后两个人的总钱数不变)
3.事务的隔离级别(了解)

  • 概念:多个事务之间是隔离的,相互独立的,但是如果多个事务操作同一批数据,则会引发一些问题,设置不同的隔离级别就可以解决这些问题。
  • 存在问题:
    • 1.脏读:一个事务,读取到另一个事务中没有提交的数据
    • 2.不可重复读(虚读):在同一个事务中,两次读取到的数据不一样。
    • 3.幻读:一个事务操作(DML)数据表中所有记录,另一个事务添加了一条数据,则第一个事务查询不到自己的修改。
  • 隔离级别:
    • read uncommitted:读未提交
      • 会产生的问题:脏读、不可重复读、幻读
    • read committed:读已提交(Oracle默认的)
      • 会产生的问题:不可重复读、幻读
    • repeatable read:可重复读(MySQL默认的)
      • 会产生的问题:幻读
    • serializable:串行化
      • 可以解决所有问题
    • 注意:隔离级别从小到大安全性越来越高,但是效率越来越低。
    • 数据库查询隔离级别:
      • select @@tx_isolation;
    • 数据库设置隔离级别:
      • set global transaction isolation level 级别字符串;
        多表查询、事务、DCL
        设置之后未生效,需要重新打开数据库进行查看才可以生效。
        多表查询、事务、DCL
        重新打开数据库连接后生效了:
        多表查询、事务、DCL
        4. 事务的隔离级别演示1
        首先打开命令提示窗口:
        多表查询、事务、DCL
        然后设置隔离级别:
set global transaction isolation level read uncommitted;
start transaction;
-- 转账操作
update account set balance = balance - 500 where id =1;
update account set balance = balance + 500 where id =2;

多表查询、事务、DCL
然后两边都开启事务:
多表查询、事务、DCL
然后一个窗口执行转账事务但是不提交,另一个窗口读取到了前面窗口为提交的数据(脏读):
多表查询、事务、DCL
然后1号窗口执行回滚rollback,2号再查询数据时没有发生变化,还是1000和1000:
多表查询、事务、DCL
解决脏读问题,设置事务级别为read committed,再将余额都变成1000:
多表查询、事务、DCL
两边都同时开启事务:
多表查询、事务、DCL
1号窗口完成转账事务,2号窗口查看数据变化情况(没变):
多表查询、事务、DCL
1号窗口提交事务(commit)后,2号窗口查看数据变化情况(变化了):
多表查询、事务、DCL
此时会产生数据不可重复读的问题,2号窗口两次读取的数据不一样,在1号窗口执行提交事务命令后,数据发生了变化。有时候要求在同一个事务里面每次查询的数据都是一样的。

5. 事务的隔离级别演示2
解决不可重复读的问题
首先设置1号窗口的事务隔离级别为repeatable read ,并重新设置两个人的余额均为1000:
多表查询、事务、DCL
两个窗口同时开启事务,然后1号窗口完成转账事务,但是没有执行提交事务,2号窗口再查看(数据未变化):
多表查询、事务、DCL
1号窗口执行事务提交后,如果2号窗口查看的数据仍然没有发生变化,则说明解决了不可重复读的问题:
多表查询、事务、DCL
6. 事务的隔离级别演示3
serializable串行化:如果一个事务在操作一个数据表,则另一个事务不能再操作这个数据表了。
首先1号设置事务隔离级别为serializable,重新打开一个2号窗口查看:
多表查询、事务、DCL
两个窗口同时开启事务,1号窗口完成转账事务,但是不提交事务,2号窗口查看,则2窗口的光标一直闪烁,一直等到1号完成事务提交为止:
多表查询、事务、DCL
1号执行事务提交后,2号窗口立马闪现数据变化情况:
多表查询、事务、DCL
三、DCL

  • SQL分类:
    • DDL:操作数据库和表
    • DML:增删改表中的数据
    • DQL:查询表中的数据
    • DCL:管理用户,授权
  • DBA:数据库管理员

DCL:管理用户,授权

  • 管理用户
  • 1.添加用户
-- 创建用户
CREATE USER '用户名'@'主机名' IDENTIFIED BY '密码';

多表查询、事务、DCL
多表查询、事务、DCL

  • 2.删除用户
-- 删除用户
DROP USER '用户名'@'主机名';

多表查询、事务、DCL

  • 3.修改用户密码
    方法1:
-- 修改lisi用户的密码为abc
-- 语法
UPDATE USER SET PASSWORD = PASSWORD('新密码') WHERE USER = '用户名';
-- 例如
UPDATE USER SET PASSWORD = PASSWORD('abc') WHERE USER = 'lisi';、

多表查询、事务、DCL
我的数据库不知道为啥密码还是原来的123,修改不了!!!

方法2:

-- 语法
SET PASSWORD FOR '用户名'@'主机名' = PASSWORD('新密码');
-- 例如
SET PASSWORD FOR 'root'@'localhost' = PASSWORD('123');
SET PASSWORD FOR 'lisi'@'%' = PASSWORD('abc');

多表查询、事务、DCL
多表查询、事务、DCL
特殊情况:MySQL中因为多次修改密码导致忘记了root用户的密码怎么办?

  1. cmd – > net stop mysql 停止mysql服务
    多表查询、事务、DCL
    多表查询、事务、DCL
    多表查询、事务、DCL

  2. 启动MySQL服务
    使用无验证方式启动MySQL服务。

mysqld --skip-grant-tables

多表查询、事务、DCL
3. 打开新的cmd窗口(管理员身份),直接输入mysql命令,敲回车,就可以登录成功
多表查询、事务、DCL
4. 然后修改root用户的密码:
use mysql;
5. update user set password = password(‘新密码’) where user = ‘root’;
多表查询、事务、DCL
6. 关闭两个窗口
7. 然后进入任务管理器结束掉mysqld.exe这个进程
多表查询、事务、DCL
8. 然后通过管理员身份进入cmd,启动mysql服务:
多表查询、事务、DCL
9. 然后通过新的密码登录数据库:
多表查询、事务、DCL

  • 4.查询用户:
-- 1.切换到mysql数据库
USE mysql;
-- 2.查询user表
SELECT * FROM USER;

通配符:% 表示可以在任意主机使用用户登录数据库。
多表查询、事务、DCL

  • 权限管理
    1. 查询权限
-- 查询权限
SHOW GRANTS FOR '用户名'@'主机名';
SHOW GRANTS FOR 'lisi'@'%';
SHOW GRANTS FOR 'root'@'%';

多表查询、事务、DCL
多表查询、事务、DCL
2. 授予权限

-- 权限授予
grant 权限列表 on 数据库名.表名 to '用户名'@'主机名';
GRANT SELECT ON db3.account TO 'lisi'@'%';

多表查询、事务、DCL
多表查询、事务、DCL
多表查询、事务、DCL
给lisi授予多个权限:

-- 权限授予
GRANT 权限列表 ON 数据库名.表名 TO '用户名'@'主机名';
GRANT SELECT ON db3.account TO 'lisi'@'%';
-- 授予多个权限
GRANT SELECT,DELETE,UPDATE ON db3.account TO 'lisi'@'%';

多表查询、事务、DCL
多表查询、事务、DCL
给张三用户授予所有权限:

-- 创建张三用户
CREATE USER 'zhangsan'@'localhost' IDENTIFIED BY '123';
-- 给张三用户授予所有权限,在任意数据库任意表上
-- 所有权限的通配符是all
GRANT ALL ON *.* TO 'zhangsan'@'localhost';

多表查询、事务、DCL
3. 撤销权限
语法:

-- 撤销权限
REVOKE 权限列表 ON 数据库名.表名 FROM '用户名'@'主机名';
-- 将李四的修改权限撤销掉
REVOKE UPDATE ON db3.`account` FROM 'lisi'@'%';

多表查询、事务、DCL

MySQL 相关文章推荐
数据库连接池
Apr 06 MySQL
jdbc使用PreparedStatement批量插入数据的方法
Apr 27 MySQL
MySQL COUNT函数的使用与优化
May 10 MySQL
MySQL的Query Cache图文详解
Jul 01 MySQL
MySQL外键约束(FOREIGN KEY)案例讲解
Aug 23 MySQL
MySQL修改默认引擎和字符集详情
Sep 25 MySQL
MySQL悲观锁与乐观锁的实现方案
Nov 02 MySQL
详解MySQL中timestamp和datetime时区问题导致做DTS遇到的坑
Dec 06 MySQL
weblogic服务建立数据源连接测试更新mysql驱动包的问题及解决方法
Jan 22 MySQL
排查MySQL生产环境索引没有效果
Apr 11 MySQL
MySQL 数据库范式化设计理论
Apr 22 MySQL
MySQL主从切换的超详细步骤
Jun 28 MySQL
Mysql Show Profile
Apr 05 #MySQL
Mysql - 常用函数 每天积极向上
Apr 05 #MySQL
mysql多表查询-笔记七
Apr 05 #MySQL
mysql部分操作
Apr 05 #MySQL
left join、inner join、right join的区别
数据库的高级查询六:表连接查询:外连接(左外连接,右外连接,UNION关键字,连接中ON与WHERE的不同)
mysql字符串截取函数小结
You might like
php读取mysql乱码,用set names XXX解决的原理分享
2011/12/29 PHP
如何使用php绘制在图片上的正余弦曲线
2013/06/08 PHP
php环境下利用session防止页面重复刷新的具体实现
2014/01/09 PHP
php魔术变量用法实例详解
2014/11/13 PHP
Laravel 5框架学习之环境与配置
2015/04/08 PHP
调试WordPress中定时任务的相关PHP脚本示例
2015/12/10 PHP
PHP的数组中提高元素查找与元素去重的效率的技巧解析
2016/03/03 PHP
PHP实现防盗链的方法分析
2017/07/25 PHP
php实现统计二进制中1的个数算法示例
2018/01/23 PHP
jquery 插件实现瀑布流图片展示实例
2015/04/03 Javascript
JavaScript返回0-1之间随机数的方法
2015/04/06 Javascript
JavaScript实现Iterator模式实例分析
2015/06/09 Javascript
使用AngularJS编写较为优美的JavaScript代码指南
2015/06/19 Javascript
微信小程序定位当前城市的方法
2018/07/19 Javascript
ES6 fetch函数与后台交互实现
2018/11/14 Javascript
jquery实现动态改变css样式的方法分析
2019/05/27 jQuery
vue实现axios图片上传功能
2019/08/20 Javascript
react的hooks的用法详解
2020/10/12 Javascript
JS将指定的某个字符全部转换为其他字符实例代码
2020/10/13 Javascript
[40:17]2018DOTA2亚洲邀请赛 4.5 淘汰赛 LGD vs Liquid 第一场
2018/04/06 DOTA
提升Python程序运行效率的6个方法
2015/03/31 Python
python模拟登录并且保持cookie的方法详解
2017/04/04 Python
解决Python安装后pip不能用的问题
2018/06/12 Python
python多进程控制学习小结
2018/10/31 Python
Django 多环境配置详解
2019/05/14 Python
pytorch 模拟关系拟合——回归实例
2020/01/14 Python
Boda Skins皮衣官网:奢侈皮夹克,全球配送
2016/12/15 全球购物
五十岁生日宴会答谢词
2014/01/15 职场文书
小学教研工作制度
2014/01/15 职场文书
《郑和远航》教学反思
2014/04/16 职场文书
学生干部培训方案
2014/06/12 职场文书
人口与计划生育目标管理责任书
2014/07/29 职场文书
民族学专业职业生涯规划范文:积跬步以至千里
2014/09/11 职场文书
员工加薪申请报告
2015/05/15 职场文书
2015年文秘个人工作总结
2015/10/14 职场文书
Django drf请求模块源码解析
2021/06/08 Python