在这篇文章中,我们将深入探讨数据库的查询技巧和方法,包括多表关系、多表查询、内连接查询、外连接查询、自连接查询,以及联合查询、子查询等多种查询方法。我们将通过清晰的图解和实例代码,展现数据在不同查询中的流动和转化,让读者一目了然。我们还将介绍事务在数据库中的作用和使用方式,详细解读事务的四大特性并讲解并发事务可能出现的问题和解决办法。此外,我们还将探讨事务的隔离级别,并通过实例代码展示如何在实际操作中使用这些功能。无论你是数据库应用的新手还是老鸟,我相信你都能在这篇文章中找到有用的信息。
一、多表关系
二、多表查询
合并查询(笛卡尔积,会展示所有组合结果):
select * from emp, dept;
笛卡尔积:两个集合A集合和B集合的所有组合情况(在多表查询时,需要消除无效的笛卡尔积)
消除无效笛卡尔积:
select * from emp, dept where emp.dept = dept.id;
三、内连接查询
隐式内连接:
SELECT 字段列表 FROM 表1, 表2 WHERE 条件 …;
显式内连接:
SELECT 字段列表 FROM 表1 [ INNER ] JOIN 表2 ON 连接条件 …;
显式性能比隐式高
例子:
-- 查询员工姓名,及关联的部门的名称 -- 隐式 select e.name, d.name from employee as e, dept as d where e.dept = d.id; -- 显式 select e.name, d.name from employee as e inner join dept as d on e.dept = d.id;
四、外连接查询
左外连接:
查询左表所有数据,以及两张表交集部分数据
SELECT 字段列表 FROM 表1 LEFT [ OUTER ] JOIN 表2 ON 条件 …;
相当于查询表1的所有数据,包含表1和表2交集部分数据
右外连接:
查询右表所有数据,以及两张表交集部分数据
SELECT 字段列表 FROM 表1 RIGHT [ OUTER ] JOIN 表2 ON 条件 …;
例子:
-- 左 select e.*, d.name from employee as e left outer join dept as d on e.dept = d.id; select d.name, e.* from dept d left outer join emp e on e.dept = d.id; -- 这条语句与下面的语句效果一样 -- 右 select d.name, e.* from employee as e right outer join dept as d on e.dept = d.id;
五、自连接查询
当前表与自身的连接查询,自连接必须使用表别名
语法:
SELECT 字段列表 FROM 表A 别名A JOIN 表A 别名B ON 条件 …;
例子:
-- 查询员工及其所属领导的名字 select a.name, b.name from employee a, employee b where a.manager = b.id; -- 没有领导的也查询出来 select a.name, b.name from employee a left join employee b on a.manager = b.id;
六、联合查询 union, union all
七、子查询
1.标量子查询
子查询返回的结果是单个值(数字、字符串、日期等)。
常用操作符:- < > > >= < <=
例子:
-- 查询销售部所有员工 select id from dept where name = '销售部'; -- 根据销售部部门ID,查询员工信息 select * from employee where dept = 4; -- 合并(子查询) select * from employee where dept = (select id from dept where name = '销售部'); -- 查询xxx入职之后的员工信息 select * from employee where entrydate > (select entrydate from employee where name = 'xxx');
2.列子查询
例子:
-- 查询销售部和市场部的所有员工信息 select * from employee where dept in (select id from dept where name = '销售部' or name = '市场部'); -- 查询比财务部所有人工资都高的员工信息 select * from employee where salary > all(select salary from employee where dept = (select id from dept where name = '财务部')); -- 查询比研发部任意一人工资高的员工信息 select * from employee where salary > any (select salary from employee where dept = (select id from dept where name = '研发部')); ## 3. ## 4. # 八、 # 九、案例 ## 1.源代码 >代码如下(示例):
3.行子查询
例子:
-- 查询与xxx的薪资及直属领导相同的员工信息 select * from employee where (salary, manager) = (12500, 1); select * from employee where (salary, manager) = (select salary, manager from employee where name = 'xxx');
4.表子查询
返回的结果是多行多列
常用操作符:IN
例子
-- 查询与xxx1,xxx2的职位和薪资相同的员工 select * from employee where (job, salary) in (select job, salary from employee where name = 'xxx1' or name = 'xxx2'); -- 查询入职日期是2006-01-01之后的员工,及其部门信息 select e.*, d.* from (select * from employee where entrydate > '2006-01-01') as e left join dept as d on e.dept = d.id;
八、事务
基本操作:
-- 1. 查询张三账户余额 select * from account where name = '张三'; -- 2. 将张三账户余额-1000 update account set money = money - 1000 where name = '张三'; -- 此语句出错后张三钱减少但是李四钱没有增加 模拟sql语句错误 -- 3. 将李四账户余额+1000 update account set money = money + 1000 where name = '李四'; -- 查看事务提交方式 SELECT @@AUTOCOMMIT; -- 设置事务提交方式,1为自动提交,0为手动提交,该设置只对当前会话有效 SET @@AUTOCOMMIT = 0; -- 提交事务 COMMIT; -- 回滚事务 ROLLBACK; -- 设置手动提交后上面代码改为: select * from account where name = '张三'; update account set money = money - 1000 where name = '张三'; update account set money = money + 1000 where name = '李四'; commit;
操作方式二:
开启事务:
START TRANSACTION 或 BEGIN TRANSACTION;
提交事务:
COMMIT;
回滚事务:
ROLLBACK;
操作实例:
start transaction; select * from account where name = '张三'; update account set money = money - 1000 where name = '张三'; update account set money = money + 1000 where name = '李四'; commit;
八、事务的四大特性
九、并发事务问题
十、事务隔离级级别
√表示在当前隔离级别下该问题会出现
Serializable 性能最低;Read uncommitted 性能最高,数据安全性最差
查看事务隔离级别:
SELECT @@TRANSACTION_ISOLATION;
设置事务隔离级别:
SET [ SESSION | GLOBAL ] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE };
SESSION 是会话级别,表示只针对当前会话有效,GLOBAL 表示对所有会话有效