数据库学习第四天
今日内容
1 表连接查询
2 子查询
3 事务
4 事务的隔离级别
5 DCL
表连接查询
1 什么是多表查询?
比如我们要查询的数据列存在于不同的表中,那么我们就需要同时对多张表进行查询,这时候就要用到多表查询
2 多表查询的分类
(1)内连接:
* 隐式内连接
* 显式内连接
(2)外连接:
*左外连接
*右外连接
3 笛卡尔积现象
如果我们同时查询两张表而不做任何处理,就会出现两张表所有数据的所有组合情况。
4 如何处理笛卡尔积现象?
我们发现上图中的表中不是所有数据都有用,只有员工表中的dept_id和部门表中的id相等的数据才有用,
因此可以这样写加上条件:select emp.name, dept.name
from emp,dept where emp.dept_id
= dept.id
;
内连接
用左边表的记录去匹配右边表的记录,如果满足条件就显示如表.外键=主表.主键
隐式内连接
看不到join关键,田间使用where指定
SELECT 字段名 FROM 左表, 右表 WHERE 条件
如·:select * from emp,dept where emp.dept_id
= dept.id
;
这里可以看到员工表中的数据和部门表中的数据匹配之后才会显示。
显式内连接
使用inner join on 语句,可以省略inner
SELECT 字段名 FROM 左表 [INNER] JOIN 右表 ON 条件
如:select * from emp e inner join dept d on e.dept_id
= d.id
;
总结内连接的操作步骤
(1) 确定查询哪些表?
(2)确定连接的条件
(3)确定查询的条件
(4)确定查询的字段
左外连接
当我们用左边的表去匹配右边的表,符合条件的显示,不符合条件的显示null,也就是说显示左边表所有的内容和左边表和右边表的交集,换句话说要优先保证左边表的显示,然后再去考虑右边表,就算有不符合右边表条件的数据也给加到表中去,并不符合的地方显示null。
比如说我们给上面的部门表加了一个销售部,但是没有任何员工属于这个部门,但是我们要保证所有部门都显示:
select * from dept d left join emp e on d.id
= e.dept_id
;
右外连接
和左外连接相同的道理,其实掌握一种就行了,工作中常用左外连接,右外连接的表移到左边,用左外连接就行了,一样的。
语法:SELECT 字段名 FROM 左表 RIGHT [OUTER ]JOIN 右表 ON 条件
子查询
概念:
1 将一个查询的结果作为另一个查询的条件
2 有查询的嵌套,内部的查询称为子查询
3 子查询要使用括号
如:我们现在需要查询开发部中有哪些员工
如果使用普通的方法:
select id from dept where name=‘开发部’ ;这里查出来开发部的id
select name from emp where dept_id=1;这里查出来开发部的员工
但是使用子查询就能一步到位:
select name from emp where dept_id=(select id from dept where name=‘开发部’);
子查询的三种结果
1 子查询的结果是单行单列
2 结果是多行单列
3 结果是多行多列
对应三种结果有不同的使用方式:
(1)单行单列:结果就当作数据使用
如上面举例的:select name from emp where dept_id=(select id from dept where name=‘开发部’);
(2)多行单列:结果集类似于一个数组,父查询使用 IN 运算符
如:查询工资大于 5000 的员工,来自于哪些部门的名字
– 先查询大于 5000 的员工所在的部门 id
select dept_id from emp where salary > 5000;
– 再查询在这些部门 id 中部门的名字
select name from dept where id in (select dept_id from emp where salary > 5000);
(3)多行多列:子查询结果只要是多列,肯定在 FROM 后面作为表,这里作为一张虚拟表,因此还要取一个别名,不然无法访问
如:查询出 2011 年以后入职的员工信息,包括部门名称
– 查询出 2011 年以后入职的员工信息,包括部门名称
– 在员工表中查询 2011-1-1 以后入职的员工
select * from emp where join_date >=‘2011-1-1’;
– 查询所有的部门信息,与上面的虚拟表中的信息组合,找出所有部门 id 等于的 dept_id
select * from dept d, (select * from emp where join_date >=‘2011-1-1’) e where
d.id
= e.dept_id ;
子查询的小结
(1)子查询结果只要是单列,则在 WHERE 后面作为条件
(2)子查询结果只要是多列,则在 FROM 后面作为表进行二次查询
事务
这里有这么一个应用场景,如果一个人去银行转账,但是扣完钱之后,出现了故障,这时候如果没有使用事务,那后面另一个账户加钱的动作就没有执行,那钱白扣了!
概念
事务执行是一个整体,所有的 SQL 语句都必须执行成功。如果其中有 1 条 SQL 语句出现异常,则所有的
SQL 语句都要回滚,整个业务执行失败。
手动提交事务
手动提交事务的语法
事务的执行情况
打开事务之后,可以开始写任意sql语句了,然后对结果进行判断,如果成功就写commit提交,如果没成功就写rollback进行回滚
自动提交事务
MySQL 默认每一条 DML(增删改)语句都是一个单独的事务,每条语句都会自动开启一个事务,语句执行完毕
自动提交事务,MySQL 默认开始自动提交事务
查看 MySQL 是否开启自动提交事务
@@表示全局变量,1 表示开启,0 表示关闭
取消自动提交事务
回滚点
什么是回滚点
在某些成功的操作完成之后,后续的操作有可能成功有可能失败,但是不管成功还是失败,前面操作都已经成
功,可以在当前成功的位置设置一个回滚点。可以供后续失败操作返回到该位置,而不是返回所有操作,这个点称
之为回滚点。
回滚点的操作语句
具体操作
- 将数据还原到 1000
- 开启事务
- 让张三账号减 3 次钱,每次 10 块
- 设置回滚点:savepoint three_times;
- 让张三账号减 4 次钱,每次 10 块
- 回到回滚点:rollback to three_times;
- 分析执行过程
总结:设置回滚点可以让我们在失败的时候回到回滚点,而不是回到事务开启的时候。
事务的隔离级别(了解)
事务的四大特性 ACID(需要记住)
并发引起的问题
MySQL 数据库有四种隔离级别
隔离级别越高,性能越差,安全性越高
MySQL 事务隔离级别相关的命令
查询隔离级别 select @@tx_isolation;
设置隔离级别 set global transaction isolation level 级别字符串;
如:set global transaction isolation level read uncommitted;
DCL
我们现在默认使用的都是 root 用户,超级管理员,拥有全部的权限。但是,一个公司里面的数据库服务器上面
可能同时运行着很多个项目的数据库。所以,我们应该可以根据不同的项目建立不同的用户,分配不同的权限来管
理和维护数据库。
注:mysqld 是 MySQL 的主程序,服务器端。mysql 是 MySQL 的命令行工具,客户端。
创建用户
语法:
CREATE USER ‘用户名’@‘主机名’ IDENTIFIED BY ‘密码’;
关键字说明:
具体操作:
创建 user1 用户,只能在 localhost 这个服务器登录 mysql 服务器,密码为 123
create user ‘user1’@‘localhost’ identified by ‘123’;
创建 user2 用户可以在任何电脑上登录 mysql 服务器,密码为 123
create user ‘user2’@’%’ identified by ‘123’;
==注意,如果想查看用户的信息,可以打开mysql库中的user表查看
给用户授权
语法:
GRANT 权限 1, 权限 2… ON 数据库名.表名 TO ‘用户名’@‘主机名’;
关键字说明:
具体操作:
给 user1 用户分配对 test 这个数据库操作的权限:创建表,修改表,插入记录,更新记录,查询
grant create,alter,insert,update,select on test.* to ‘user1’@‘localhost’;
用户名和主机名要与上面创建的相同,要加单引号。
给 user2 用户分配所有权限,对所有数据库的所有表
撤销授权
语法:
REVOKE 权限 1, 权限 2… ON 数据库.表名 revoke all on test.* from ‘user1’@‘localhost’; ‘用户名’@‘主机
名’;
关键字说明:
具体操作:
撤销 user1 用户对 test 数据库所有表的操作的权限
revoke all on test.* from ‘user1’@‘localhost’;
用户名和主机名要与创建时相同,各自要加上单引号
查看权限
语法:
SHOW GRANTS FOR ‘用户名’@‘主机名’;
删除用户
语法:
DROP USER ‘用户名’@‘主机名’;
如果忘记了管理员的密码,也就是一般root的密码液有方法。具体看笔记。