多表查询|事务|DCL
第一大块 多表查询
一、笛卡尔积
- a.有两个集合A,B,去这两个集合的所有组成情况
- b.要完成多表查询,需要消除无用的数据。
- c.多表查询的分类
1.内链接查询
2.外链接查询
3.子查询
二、内连接查询(会自动忽略null字段,并且比较条件的不同,两边的表的行数也是不确定的,会变化的,这是与外连接的一个不同点;)
- a.隐式内连接:SELECT 字段名 FROM 左表, 右表 WHERE 条件
新的语法:表名.字段名 代表指定表中的指定字段
表名 as 表的别名 用在from关键字的后面
- b.显式内连接:
语法:SELECT 字段名 FROM 左表 [INNER] JOIN 右表 ON 条件
inner是可以省略的
- c.内连接查询的思路:
1.从哪些表中查询数据
2.条件是什么
3.查询哪些字段
三、外连接查询(可以对null值的字段进行查询,并且有一边的表的所有行的数据必须全部被显示出来)
- a.左外连接
语法:select 字段列表 from 表1 left [outer] join 表2 on条件;
意义:查询的是左表中所有的数据以及和另外一张表的交集部分。
- b.右外连接
语法:select 字段列表 from 表1 right [outer] join 表2 on条件;
意义:同左表查询。
四、子查询
- a.概念:查询中嵌套查询,称嵌套查询为子查询。
- b.子查询的不同种情况
1.子查询的结果是单行单列的:(都是通过一张表来获取一个值来比较,聚合函数的使用比较典型)
子查询可以作为判断条件,使用运算符去判断。运算符:< > =
2.子查询的结果是多行单列的:(通过一张表来获取一个列的多个值,然后比较,这里的in的用法和查询语句返回的值比较特殊,需要注意观察)
子查询可以作为条件,使用运算符in来判断。
3.子查询的结果是多行多列的:(实质上就是两张表之间的比较)
子查询可以作为一张虚拟表参与查询(其实就是作为另外一张表,放在from关键字之后)
- c.示例:
– ----------------------------子查询 单行单列---------------------------
– 1) 查询最高工资是多少
select max(salary) from emp;
– 2) 根据最高工资到员工表查询到对应的员工信息
select * from emp where salary = (select max(salary) from emp);
– 1) 查询平均工资是多少
select avg(salary) from emp;
– 2) 到员工表查询小于平均的员工信息
select * from emp where salary < (select avg(salary) from emp);
– ----------------------------子查询 多行单列---------------------------
– 先查询大于 5000 的员工所在的部门 id
select dept_id from emp where salary > 5000;
– 再查询在这些部门 id 中部门的名字 Subquery returns more than 1 row
select name from dept where id = (select dept_id from emp where salary > 5000);
select name from dept where id in (select dept_id from emp where salary > 5000);
– 先查询开发部与财务部的 id
select id from dept where name in(‘开发部’,‘财务部’);
– 再查询在这些部门 id 中有哪些员工
select * from emp where dept_id in (select id from dept where name in(‘开发部’,‘财务部’));
– ----------------------------子查询 多行多列---------------------------
– 查询出 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 ;
select * from emp inner join dept on emp.dept_id
= dept.id
where join_date >=‘2011-1-1’;
select * from emp inner join dept on emp.dept_id
= dept.id
and join_date >=‘2011-1-1’;
五、多表查询练习(新添加知识点,一个查询语句中可以对一张表去两个别名,这样就可以对两张一样的表进行操作)
– 部门表
CREATE TABLE dept (
id INT PRIMARY KEY PRIMARY KEY, – 部门id
dname VARCHAR(50), – 部门名称
loc VARCHAR(50) – 部门所在地
);
– 添加4个部门
INSERT INTO dept(id,dname,loc) VALUES
(10,‘教研部’,‘北京’),
(20,‘学工部’,‘上海’),
(30,‘销售部’,‘广州’),
(40,‘财务部’,‘深圳’);
– 职务表,职务名称,职务描述
CREATE TABLE job (
id INT PRIMARY KEY,
jname VARCHAR(20),
description VARCHAR(50)
);
– 添加4个职务
INSERT INTO job (id, jname, description) VALUES
(1, ‘董事长’, ‘管理整个公司,接单’),
(2, ‘经理’, ‘管理部门员工’),
(3, ‘销售员’, ‘向客人推销产品’),
(4, ‘文员’, ‘使用办公软件’);
– 员工表
CREATE TABLE emp (
id INT PRIMARY KEY, – 员工id
ename VARCHAR(50), – 员工姓名
job_id INT, – 职务id
mgr INT , – 上级领导
joindate DATE, – 入职日期
salary DECIMAL(7,2), – 工资
bonus DECIMAL(7,2), – 奖金
dept_id INT, – 所在部门编号
CONSTRAINT emp_jobid_ref_job_id_fk FOREIGN KEY (job_id) REFERENCES job (id),
CONSTRAINT emp_deptid_ref_dept_id_fk FOREIGN KEY (dept_id) REFERENCES dept (id)
);
– 添加员工
INSERT INTO emp(id,ename,job_id,mgr,joindate,salary,bonus,dept_id) VALUES
(1001,‘孙悟空’,4,1004,‘2000-12-17’,‘8000.00’,NULL,20),
(1002,‘卢俊义’,3,1006,‘2001-02-20’,‘16000.00’,‘3000.00’,30),
(1003,‘林冲’,3,1006,‘2001-02-22’,‘12500.00’,‘5000.00’,30),
(1004,‘唐僧’,2,1009,‘2001-04-02’,‘29750.00’,NULL,20),
(1005,‘李逵’,4,1006,‘2001-09-28’,‘12500.00’,‘14000.00’,30),
(1006,‘宋江’,2,1009,‘2001-05-01’,‘28500.00’,NULL,30),
(1007,‘刘备’,2,1009,‘2001-09-01’,‘24500.00’,NULL,10),
(1008,‘猪八戒’,4,1004,‘2007-04-19’,‘30000.00’,NULL,20),
(1009,‘罗贯中’,1,NULL,‘2001-11-17’,‘50000.00’,NULL,10),
(1010,‘吴用’,3,1006,‘2001-09-08’,‘15000.00’,‘0.00’,30),
(1011,‘沙僧’,4,1004,‘2007-05-23’,‘11000.00’,NULL,20),
(1012,‘李逵’,4,1006,‘2001-12-03’,‘9500.00’,NULL,30),
(1013,‘小白龙’,4,1004,‘2001-12-03’,‘30000.00’,NULL,20),
(1014,‘关羽’,4,1007,‘2002-01-23’,‘13000.00’,NULL,10);
– 工资等级表
CREATE TABLE salarygrade (
grade INT PRIMARY KEY, – 级别
losalary INT, – 最低工资
hisalary INT – 最高工资
);
– 添加5个工资等级
INSERT INTO salarygrade(grade,losalary,hisalary) VALUES
(1,7000,12000),
(2,12010,14000),
(3,14010,20000),
(4,20010,30000),
(5,30010,99990);
– 需求:
– 1.查询所有员工信息。查询员工编号,员工姓名,工资,职务名称,职务描述
/*
分析:
1.员工编号,员工姓名,工资,需要查询emp表 职务名称,职务描述 需要查询job表
2.查询条件 emp.job_id = job.id
*/
SELECT
t1.id
, – 员工编号
t1.ename
, – 员工姓名
t1.salary
,-- 工资
t2.jname
, – 职务名称
t2.description
– 职务描述
FROM
emp t1, job t2
WHERE
t1.job_id
= t2.id
;
– 2.查询员工编号,员工姓名,工资,职务名称,职务描述,部门名称,部门位置
/*
分析:
- 员工编号,员工姓名,工资 emp 职务名称,职务描述 job 部门名称,部门位置 dept
- 条件: emp.job_id = job.id and emp.dept_id = dept.id
*/
SELECT
t1.id
, – 员工编号
t1.ename
, – 员工姓名
t1.salary
,-- 工资
t2.jname
, – 职务名称
t2.description
, – 职务描述
t3.dname
, – 部门名称
t3.loc
– 部门位置
FROM
emp t1, job t2,dept t3
WHERE
t1.job_id
= t2.id
AND t1.dept_id
= t3.id
;
– 3.查询员工姓名,工资,工资等级
/*
分析:
1.员工姓名,工资 emp 工资等级 salarygrade
2.条件 emp.salary >= salarygrade.losalary and emp.salary <= salarygrade.hisalary
emp.salary BETWEEN salarygrade.losalary and salarygrade.hisalary
/
SELECT
t1.ename ,
t1.salary
,
t2.
FROM emp t1, salarygrade t2
WHERE t1.salary
BETWEEN t2.losalary
AND t2.hisalary
;
– 4.查询员工姓名,工资,职务名称,职务描述,部门名称,部门位置,工资等级
/*
分析:
- 员工姓名,工资 emp , 职务名称,职务描述 job 部门名称,部门位置,dept 工资等级 salarygrade
- 条件: emp.job_id = job.id and emp.dept_id = dept.id and emp.salary BETWEEN salarygrade.losalary and salarygrade.hisalary
*/
SELECT
t1.ename
,
t1.salary
,
t2.jname
,
t2.description
,
t3.dname
,
t3.loc
,
t4.grade
FROM
emp t1,job t2,dept t3,salarygrade t4
WHERE
t1.job_id
= t2.id
AND t1.dept_id
= t3.id
AND t1.salary
BETWEEN t4.losalary
AND t4.hisalary
;
第二大块 事务
一、事务的基本介绍
- a.概念:如果一个包含多个步骤的业务操作(通常需要更改数据的操作可以被认为是业务操作),
被事务管理,那么这些宝座要么同时成功,要么同时失败。transcation–更新数据
- b.语法:start transaction; commit; rollback;
注意(我这里的注意点是在mysql的事务提交方式设置为自动提交的情况下适用的):1.事务一旦被回滚或者提交,那么这个事务就被关闭,进行下一次业务就需要重新开启事务。
2.事务在没有被回滚或者提交的情况下会一直保存最原先的开启事务时的那一份数据,不管你的业务代码
执行多少次,只要一回滚,那么就会回到最原始的那份数据。
- c.事务的自动提交和手动提交(在mysql中事务提交方式默认是自动提交,所以这是我写的注意点中的原理;而oracle中默认是手动提交)
语法:
查询mysql数据库事务提交方式:select @@autocommit; 返回值是1代表自动提交,是0代表手动提交
设置mysql数据库事务提交方式:set @@autocommit=0;或者设为1
二、事物的四大特征
- a.原子性:事务是不可分割的最小操作单位,要么同时成功,要么同时失败。
- b.持久性:当事务提交或者回滚后,数据库会发生持久化的保存数据。
- c.隔离性:多个事物之间。相互独立。
- d.一致性:实务操作的前后,数据总量不变。
三、事务的隔离级别(了解)
- a.概念:多个事物之间格力的,相互独立的。但是如果多个实务操作同一批数据,则会引发一些问题,
设置不同的隔离级别就可以解决这些问题。
- b.存在的问题
1.赃读:一个事物,读取到另一个事物没有提交的数据;
2.不可重复读(虚读):同一个事务中,两次读取到的数据不一样;
3.幻读:一个书屋操作(DML)数据表中所有的记录,另一个是无添加了一条数据,则第一个事务查询不到自己的修改。
4.这些问题存在的原理:因为我们可以有多台设备对同一个数据库进行操作,所以这样的话就会出现以上的问题。
,所以我们可以同时在两个不同的窗口开启两个不同的事务(例如两个cmd窗口同时操作一个数据库)
- c.隔离级别:
1.read uncommitted:读未提交 问题:1、2、3
2.read committed:(Oracle默认隔离级别)读已提交 问题:2、3 运作原理:在另外一个事务提交了了之后,我这个事务才可以对另外一个事务中处理的数据操作
3.repeatable read:(mysql默认隔离级别)可重复读 问题:3 运作原理:即使另外一个事务改变了部分的数据内容,但是我这个事务从我打开时已经以我打开这个事务时的数据情况作了一个固定操作,那么在我没有提交或者滚回事务时,我这个事务中的数据不受除了我这个事务之外其他任何事务的影响,从而达到操作我这个事务时我每次查到的数据都是一样的。
4.serializable:串行化 问题:全部解决 原理:就是如果一个事物在操作一个表时,其他事务是不能对着张数据表进行操作的。类似于java中多线程中的锁机制。
5.注意点:隔离级别从小到大,安全程度逐渐提高。但是效率逐渐降低,所以需要我们按需分配,保证效率高的同时,安全也有保证。
- d.隔离级别的设置(注意在每次设置之后需要从新登陆数据库才可以生效):
查询隔离级别 select @@tx_isolation; isolation 隔离
设置隔离级别 set global transaction isolation level 级别字符串;
- e.各个级别的原理精简解释(基于同一个数据,两个不同事务同时运作的情况解析):级别一,可以读取到另外一个事物中未提交但是改变了的数据值;级别二,可以读取到另外一个事务提交了的改变了的数据,并且另外一个事务如果多次提交,多次更改数据,那么本事务中多次读到的数据会变化;级别三,无论另外一个事务怎么更改多次提交,只要本事务没有提交,另外一个事务做的操作对本事务的正在操作的数据没有影响。
第三大块 DCL 管理用户,并且对用户进行授权
一、DCL概述
- a.拓展知识:公司里的DBA(数据库管理员)专门写DCL代码
- b.意义:管理用户,对用户进行授权。
二、DCL 管理用户,授权
- a.管理用户
1.添加用户:在mysql数据库中的user表中可以看到用户
格式:create user ‘用户名’@‘主机名’ identified by ‘密码’;
示例:注意的是就是主机名可以使用%占位符作为所有主机都可以登录;而localhost是指只有本机才可以登录指定数据库;
create user ‘yezhiyue’@’%’ identified by ‘4321’;
create user ‘user1’@‘localhost’ identified by ‘4321’;
2.删除用户:
格式:
drop user ‘用户名’@‘主机名’;
示例:
drop user ‘user1’@‘localhost’;
3.修改用户密码:
格式:
update user set password = password(‘新密码’) where user=‘用户名’;
set password for ‘用户名’@‘主机名’=password(‘新密码’);
示例:
update user set password = password(‘user1’) where user=‘4321’;
set password for ‘user1’@‘localhost’=password(‘4321’);
4.查询用户:(权限列表,也就是类似于权限 1, 权限 2…的形式,权限关键字 CREATE、ALTER、SELECT、INSERT、UPDATE等)
– 查询权限 (grant 授予)
SHOW GRANTS FOR ‘用户名’@‘主机名’;
SHOW GRANTS FOR ‘lisi’@’%’;
- 授予权限:(可以使用通配符*)
– 授予权限
grant 权限列表 on 数据库名.表名 to ‘用户名’@‘主机名’;
– 给张三用户授予所有权限,在任意数据库任意表上
GRANT ALL ON . TO ‘zhangsan’@‘localhost’;
3. 撤销权限:(可以使用通配符*)
– 撤销权限:
revoke 权限列表 on 数据库名.表名 from ‘用户名’@‘主机名’;
REVOKE UPDATE ON db3.account
FROM ‘lisi’@’%’;
- b.补充:如果你忘记了root用户的密码,也就是最高管理员,这是你就可以通过一
系列复杂的操作去重新修改这个最高管理员的密码。
示例: * mysql中忘记了root用户的密码?
- cmd – > net stop mysql 停止mysql服务
- 需要管理员运行该cmd
- 使用无验证方式启动mysql服务: mysqld --skip-grant-tables
- 打开新的cmd窗口,直接输入mysql命令,敲回车。就可以登录成功
- use mysql;
- update user set password = password(‘你的新密码’) where user = ‘root’;
- 关闭两个窗口
- 打开任务管理器,手动结束mysqld.exe 的进程
- 启动mysql服务
- 使用新密码登录。