初识MySQL(三) 多表查询,事务,DCL

一. 多表查询

1. 数据准备:

# 创建部门表
CREATE TABLE dept(
	id INT PRIMARY KEY AUTO_INCREMENT,
	NAME VARCHAR(20)
)
INSERT INTO dept (NAME) VALUES ('开发部'),('市场部'),('财务部');
# 创建员工表
CREATE TABLE emp (
	id INT PRIMARY KEY AUTO_INCREMENT,
	NAME VARCHAR(10),
	gender CHAR(1), -- 性别
	salary DOUBLE, -- 工资
	join_date DATE, -- 入职日期
	dept_id INT,
	FOREIGN KEY (dept_id) REFERENCES dept(id) -- 外键,关联部门表(部门表的主键)
)
INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('孙悟空','男',7200,'2013-02-24',1);
INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('猪八戒','男',3600,'2010-12-02',2);
INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('唐僧','男',9000,'2008-08-08',2);
INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('白骨精','女',5000,'2015-10-07',3);
INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('蜘蛛精','女',4500,'2011-03-14',1);

2. 多表查询的作用:

比如:我们想查询孙悟空的名字和他所在的部门的名字,则需要使用多表查询。
如果一条 SQL 语句查询多张表,因为查询结果在多张不同的表中。每张表取 1 列或多列。

  • 多表查询的分类:

3. 笛卡尔积现象:

– 需求:查询所有的员工和所有的部门

select * from emp,dept;

查询结果为:

结果分析:
左边的每条数据和右边的每条数据组合,这种效果被称为笛卡尔积。

所以要完成多表查询,我们需要消除笛卡尔积的影响。
– 设置过滤条件:

select * from emp,dept where emp.`dept_id` = dept.`id`;


– 查询员工和部门的名字

SELECT emp.`name`, dept.`name` FROM emp,dept WHERE emp.`dept_id` = dept.`id`;

4. 内连接查询

用左边表的记录去匹配右边表的记录,如果符合条件的则显示。如:从表.外键=主表.主键;

4.1 隐式内连接:

语法:

SELECT 字段名 FROM 左表, 右表 WHERE 条件
  • 示例:
select * from emp,dept where emp.dept_id = dept.id;

4.2 显示内连接

使用 INNER JOIN … ON 语句, 可以省略 INNER;

  • 语法:
SELECT 字段名 FROM 左表 [INNER] JOIN 右表 ON 条件;

演示:

SELECT * FROM emp e JOIN dept d ON e.`dept_id`=d.`id`;

5. 外连接查询

5.1 左外连接:

使用 LEFT OUTER JOIN … ON, OUTER 可以省略

  • 语法:
SELECT 字段名 FROM 左表 LEFT [OUTER] JOIN 右表 ON 条件
  • 查询的是左表所有数据以及其交集部分。
  • 演示:
-- 使用左外连接查询
SELECT * FROM dept d LEFT JOIN emp e ON d.`id` = e.`dept_id`;


注意:

-- 在部门表中增加一个销售部
INSERT INTO dept (NAME) VALUES ('销售部');
SELECT * FROM dept;

-- 使用左外连接查询
SELECT * FROM dept d LEFT JOIN emp e ON d.`id` = e.`dept_id`;

5.2 右外连接:

使用 RIGHT OUTER JOIN … ON, OUTER 可以省略

  • 语法:
SELECT 字段名 FROM 左表 RIGHT [OUTER ]JOIN 右表 ON 条件
  • 查询的是右表所有数据以及其交集部分。
  • 演示:
-- 使用右外连接查询
SELECT * FROM dept d RIGHT JOIN emp e ON d.`id` = e.`dept_id`;

6. 子查询

6.1 子查询的概念:

  1. 一个查询的结果做为另一个查询的条件
  2. 有查询的嵌套,内部的查询称为子查询
  3. 子查询要使用括号

6.2 子查询结果的三种情况

  • 子查询的结果是单行单列
    语法:
SELECT 查询字段 FROMWHERE 字段=(子查询) ;

子查询可以作为条件,使用运算符去判断。 运算符: > >= < <= =等。
演示:
– 1 查询工资低于平均工资的员工信息

SELECT * FROM emp WHERE salary < (SELECT AVG(salary) FROM emp);

  • 子查询的结果是多行单列
    子查询结果是单例多行,结果集类似于一个数组,父查询使用 IN 运算符
    语法:
SELECT 查询字段 FROMWHERE 字段 IN (子查询) ;

演示:
– 查询工资大于 5000 的员工,来自于哪些部门的名字

SELECT NAME FROM dept WHERE id IN (SELECT dept_id FROM emp WHERE salary>5000);

  • 子查询的结果是多行多列
    语法:
SELECT 查询字段 FROM (子查询) 表别名 WHERE 条件;

注意:子查询作为表需要取别名,否则这张表没有名称则无法访问表中的字段

演示:
– 查询出 2011 年以后入职的员工信息,包括部门名称

SELECT * FROM dept d, (SELECT * FROM emp WHERE join_date >='2011-1-1') e WHERE d.`id`= e.dept_id ;

二. 事务

1. 什么是事务

在实际的开发过程中,一个业务操作如:转账,往往是要多次访问数据库才能完成的。转账是一个用户扣钱,另一个用户加钱。如果其中有一条 SQL 语句出现异常,这条 SQL 就可能执行失败。

事务执行是一个整体, 所有的 SQL 语句都必须执行成功。如果其中有 1 条 SQL 语句出现异常, 则所有的SQL 语句都要回滚,整个业务执行失败。

2. 事务的操作:

  1. 开启事务: start transaction;
  2. 回滚:rollback;
  3. 提交:commit;
  • 演示:
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
-- 出错了...
UPDATE account SET balance = balance + 500 WHERE NAME = 'lisi';
-- 发现执行没有问题,提交事务
COMMIT;
-- 发现出问题了,回滚事务
ROLLBACK;
SELECT * FROM account;

3. 事务提交的两种方式

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

4. 事务的四大特征:

  1. 原子性:是不可分割的最小操作单位,要么同时成功,要么同时失败。
  2. 持久性:当事务提交或回滚后,数据库会持久化的保存数据。
  3. 隔离性:多个事务之间。相互独立。
  4. 一致性:事务操作前后,数据总量不变

5. 事务的隔离级别(了解)

5.1 概念

多个事务之间隔离的,相互独立的。但是如果多个事务操作同一批数据,则会引发一些问题,设置不同的隔离级别就可以解决这些问题。

5.2 存在问题:

  1. 脏读:一个事务,读取到另一个事务中没有提交的数据
  2. 不可重复读(虚读):在同一个事务中,两次读取到的数据不一样。
  3. 幻读:一个事务操作(DML)数据表中所有记录,另一个事务添加了一条数据,则第一个事务查询不到自己的修改。

5.3 隔离级别:

  • read uncommitted:读未提交
    产生的问题:脏读、不可重复读、幻读

  • read committed:读已提交 (Oracle)
    产生的问题:不可重复读、幻读

  • repeatable read:可重复读 (MySQL默认)
    产生的问题:幻读

  • serializable:串行化
    可以解决所有的问题

  • 注意:隔离级别从小到大安全性越来越高,但是效率越来越低

  • 数据库查询隔离级别:

    • select @@tx_isolation;
  • 数据库设置隔离级别:

    • set global transaction isolation level 级别字符串;

三. DCL

  • DCL : 管理用户,授权;

我们现在默认使用的都是 root 用户, 超级管理员, 拥有全部的权限。但是, 一个公司里面的数据库服务器上面
可能同时运行着很多个项目的数据库。所以, 我们应该可以根据不同的项目建立不同的用户, 分配不同的权限来管
理和维护数据库。

注: mysqld 是 MySQL 的主程序,服务器端。 mysql 是 MySQL 的命令行工具,客户端。

1. 管理用户

  • 添加用户:
    语法:
CREATE USER '用户名'@'主机名' IDENTIFIED BY '密码';
  • 删除用户:
    语法:
DROP USER '用户名'@'主机名';
  • 修改用户密码:
    语法:
UPDATE USER SET PASSWORD = PASSWORD('新密码') WHERE USER = '用户名';

当然,也可以简化一点:

SET PASSWORD FOR '用户名'@'主机名' = PASSWORD('新密码');
  • mysql中忘记了root用户的密码?

    1. cmd – > net stop mysql 停止mysql服务
      * 需要管理员运行该cmd
    2. 使用无验证方式启动mysql服务: mysqld --skip-grant-tables
    3. 打开新的cmd窗口,直接输入mysql命令,敲回车。就可以登录成功
    4. use mysql;
    5. update user set password = password(‘你的新密码’) where user = ‘root’;
    6. 关闭两个窗口
    7. 打开任务管理器,手动结束mysqld.exe 的进程
    8. 启动mysql服务
    9. 使用新密码登录。
  • 查询用户:

  1. 切换到mysql数据库
    USE myql;
  2. 查询user表
    SELECT * FROM USER;
  • 通配符: % 表示可以在任意主机使用用户登录数据库

2. 权限管理:

  • 查询权限:
    语法
SHOW GRANTS FOR '用户名'@'主机名';
  • 授予权限:
    语法:
grant 权限列表 on 数据库名.表名 to '用户名'@'主机名';
  • 撤销权限:
    语法:
revoke 权限列表 on 数据库名.表名 from '用户名'@'主机名';

猜你喜欢

转载自blog.csdn.net/qq_41879343/article/details/88713613