多表查询、事务、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 相关文章推荐
MySQL查询学习之基础查询操作
May 08 MySQL
MySQL优化之如何写出高质量sql语句
May 17 MySQL
MySQL 使用事件(Events)完成计划任务
May 24 MySQL
MySQL通过binlog恢复数据
May 27 MySQL
mysql中between的边界,范围说明
Jun 08 MySQL
Centos7中MySQL数据库使用mysqldump进行每日自动备份的编写
Aug 02 MySQL
浅谈MySQL之select优化方案
Aug 07 MySQL
MySQL创建管理KEY分区
Apr 13 MySQL
详细介绍MySQL中limit和offset的用法
May 06 MySQL
MySql数据库 查询时间序列间隔
May 11 MySQL
mysql sock 文件解析及作用讲解
Jul 15 MySQL
MySQL索引失效场景及解决方案
Jul 23 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
腾讯QQ微博API接口获取微博内容
2013/10/30 PHP
PHP小教程之实现双向链表
2014/06/12 PHP
PHP实现多文件上传的方法
2015/07/08 PHP
Yii框架ACF(accessController)简单权限控制操作示例
2019/04/26 PHP
小议Function.apply()之二------利用Apply的参数数组化来提高 JavaScript程序性能
2006/11/30 Javascript
让IE6支持min-width和max-width的方法
2010/06/25 Javascript
jquery 查找select ,并触发事件的实现代码
2011/03/30 Javascript
对于this和$(this)的个人理解
2013/09/08 Javascript
js如何实现点击标签文字,文字在文本框出现
2015/08/05 Javascript
全面解析Bootstrap中tooltip、popover的使用方法
2016/06/13 Javascript
jQuery easyui刷新当前tabs的方法
2016/09/23 Javascript
炫酷的js手风琴效果
2016/10/13 Javascript
JavaScript日期选择功能示例
2017/01/16 Javascript
js中document.referrer实现移动端返回上一页
2017/02/22 Javascript
bootstrap table实现点击翻页功能 可记录上下页选中的行
2017/09/28 Javascript
深入Vue-Router路由嵌套理解
2018/08/13 Javascript
解决VUE中document.body.scrollTop为0的问题
2018/09/15 Javascript
layui 中select下拉change事件失效的解决方法
2019/09/20 Javascript
[03:07]2015国际邀请赛选手档案EHOME.rOtK 是什么让他落泪?
2015/07/31 DOTA
[51:27]LGD vs Liquid 2019国际邀请赛小组赛 BO2 第二场 8.16
2019/08/19 DOTA
python模拟登录百度代码分享(获取百度贴吧等级)
2013/12/27 Python
PyQt5每天必学之日历控件QCalendarWidget
2018/04/19 Python
python实现ID3决策树算法
2018/08/29 Python
python学生管理系统的实现
2020/04/05 Python
python使用正则表达式匹配txt特定字符串(有换行)
2020/12/09 Python
HTML5 离线应用之打造零请求、无流量网站的解决方法
2013/04/25 HTML / CSS
纽约家具、家居装饰和地毯店:ABC Carpet & Home
2017/06/21 全球购物
Gap英国官网:Gap UK
2018/07/18 全球购物
化工专业推荐信范文
2013/11/28 职场文书
董事长秘书职责
2014/01/31 职场文书
《美丽的小兴安岭》教学反思
2014/02/26 职场文书
文体活动总结范文
2014/05/05 职场文书
结对共建工作方案
2014/06/02 职场文书
交通事故协议书范本
2014/11/18 职场文书
2014年为民办实事工作总结
2014/12/20 职场文书
六年级小学生评语
2014/12/26 职场文书