数据库操作(七)

回顾:
1、sql的执行顺序
select ⑤
from ①
where ②
group by ③
having ④
order by ⑥

2、关联查询
多表联合查询,杜绝笛卡尔积现象。
要求N张表联合,必须至少有N-1个连接条件。
内连接:查询出所有满足连接条件的数据。

外连接:查询出数据,满足+不满足条件的数据
左外连接
左表驱动表(所有数据)+ 右表匹配表(匹配)
右外连接
左表匹配表(匹配)+ 右表驱动表(所有数据)
全外连接
左表驱动表(所有数据)+ 右表驱动表(所有数据)
自连接
特殊连接查询
驱动、匹配表都来自于同一张表。

正课:
1、子查询
你是sql大牛,能否写一条select sql就能查询出想要的数据。
如:查询30部门最大工资的员工信息。
--错

    select *,max(sal) from emp 
        where deptno = 30;
select * from emp where deptno = 30
        and sal = (
            --30部门最高工资
            select max(sal) from emp 
            where deptno = 30
        );

如上所述:
当无法使用一条select sql完成一个功能时,
可以考虑使用sql嵌套的方式来完成。

sql嵌套:
一条SQL语句中嵌套着另一条SQL查询语句。
又被称为---子查询。

被嵌套在SQL语句中的查询SQL,称为子查询,
子查询所在的那条SQL语句,称为父查询。

注意:子查询可以使用在DDL、DML、DQL中,
通常一般使用在DQL中为多。

1)、子查询使用在DDL中

    create table emp_copy
        as (select empno,ename,job,sal,deptno 
            from emp
            );

结论:子查询使用在建表语句中,
实为表结构、表数据的复制。

2)、子查询使用在DML中

    insert into emp_copy 
        --values 注意:连values都没有
        (
            select empno,ename,job,sal,deptno 
            from emp
        );

3)、子查询使用在DQL中
DQL结构
select
from
where
group by 不使用子查询
having
order by 不使用子查询r

子查询的分类
   根据子查询的结果,可将子查询分为:

①、单行单列子查询。
select max(sal) from emp
where deptno = 30;--查询30部门的最高工资(1个)
②、多行单列子查询。
select empno from emp
where deptno = 30;--查询30部门的员工编号(多个)
③、多行多列子查询。
select empno,ename,sal,deptno
from emp
where deptno = 30;--查询30部门的员工信息(编号,姓名,工资,部门编号)(多条)

3-1)、子查询使用在where子句中
--查询与JONES员工相同部门的其他员工信息。
--step1:查询JONES员工所在部门
select deptno from emp where ename='JONES';
--step2:部门等于JONES部门的员工(其他员工)
select * from emp where deptno = (step1的结果)
and ename <> 'JONES';
--step3:sql拼接。

       select * from emp 
        where deptno = (
            --单行单列子查询
            select deptno from emp where ename='JONES'
        )
        and ename <> 'JONES';

--查询与SMITH、ALLEN不在同一个部门的员工信息。
--step1:查询出SMITH、ALLEN所在部门
select deptno from emp
where ename = 'SMITH' or ename = 'ALLEN';--in ('SMITH'、'ALLEN')

--step2:查询不在SMITH、ALLEN部门的员工
select * from emp
where deptno not in (step1的结果);
--step3:sql拼接
select * from emp
where deptno not in (
--多行单列子查询
select deptno from emp
where ename = 'SMITH' or ename = 'ALLEN'
);
注意:where子句中,可以出现单行单列、多行单列子查询。
单行单列子查询,一般使用 =、!=、<...
多行单列子查询,一般使用 in、any、all。

    ***补充:
       在子查询中,需要引入主查询的某些字段数据。
        可以使用exists关键字。
    
       --查询有员工的部门信息
       方式一:内连接方式
        select d.* from emp e,dept d
        where e.deptno = d.deptno;

       方式二:使用exists关键字
        select * from dept d
        where exists --存在以下关系
        (
            --只需要存在这种关系即可
            --能有返回值,说明关系存在
            --所以无需关系确切的返回数据内容
            select 1 from emp e
            where e.deptno = d.deptno
        );

3-2)、子查询使用在having子句中
--查收出最低薪水 高于 30部门最低薪水
的部门信息(部门编号、最低薪水)。
--step1:查询出30部门的最低薪水
select min(sal) from emp where deptno=30;

--step2:查询出各部门的最低薪水
select deptno,min(sal)
from emp
group by deptno;

--step3:最低薪水对比
select deptno,min(sal)
from emp
--where 后面无法使用聚合函数
--where min(sal) > (step1的结果)
group by deptno
--但是having可以使用聚合函数
having min(sal) > (step1的结果);

--step4:sql拼接

       select deptno,min(sal) 
        from emp 
        --where 后面无法使用聚合函数
        --where min(sal) > (step1的结果)
        group by deptno
        --但是having可以使用聚合函数
        having min(sal) > (
            select min(sal) from emp 
            where deptno=30
        );

3-3)、子查询使用from子句中
from 后面跟 表(多行多列结构)
所以一般多行多列子查询会充当临时表(虚表、匿名视图)
的功能,使用在from后面。

多行多列子查询作为临时表,该表并不存在,
查询到的数据,也只能在当前sql中有效。

--查询与30部门员工职位、工资都相同的
其他部门员工信息。
--step1:先查出30部门的职位及工资
select job,sal from emp
where deptno=30;
--step2:查询其他部门中员工信息
select * from emp
where deptno <> 30;
--step3:职位与工资匹配
select o.*
from (step2结果) o --其他部门人员,
(step1结果) th --30部门职位及工资
where o.job = th.job
and o.sal = th.sal;
--step4:sql

        select o.* 
        from (select * from emp 
            where deptno <> 30) o, --其他部门人员,
             (select job,sal from emp
            where deptno=30) th --30部门职位及工资
        where o.job = th.job
        and o.sal = th.sal;

3-4)、子查询使用在select语句中
把子查询放在select子句中,在一定程度上
可以充当外连接效果。

    --查询所有部门部门信息
    select distinct d.*,
    (select deptno from dept 
            where deptno not in(
            select distinct deptno from emp 
            where deptno is not null)) noEmpDept  
    from dept d,emp e
    where d.deptno = e.deptno;

    或给一个确切的值
    select distinct d.*,40 as noEmpDept  
    from dept d,emp e
    where d.deptno = e.deptno;

4、总结:
1)、子查询根据查询结果可分为:
单行单列子查询 (1个值)
多行单列子查询 (多个值)
多行多列子查询 (多条数据)

2)、子查询可以使用在DDL、DML、DQL中。
其中使用在DQL中居多。

3)、一条完整的DQL查询语句,如下:
select
from
where
group by
having
order by
一般 group by、order by后面跟查询表的字段名。
不能乱使用子查询的结果。

     select、from、where、having中可以使用子查询。
    a、其中where、having后面可以跟上
        单行单列子查询 一般使用 =、!=、>、<等关系运算符。
        多行单列子查询 一般使用 in、not in、any、all

    b、from后面可以跟上
        多行多列子查询 充当临时表。

    c、select后面只能跟上
        单行单列子查询(一般不建议这么用)

补充:
1、删除数据
truncate table emp_copy;--删除数据,保留表结构
delete from emp_copy;--全表删除数据
--truncate、delete的区别:
truncate不需要TCL支持
delete必须TCL支持

2、任何一个大功能sql都是由一个个小功能sql拼起来的。
一定要将功能进行分解,分出一个个小功能。
将小功能先完成,最后做拼接。

你可能感兴趣的:(数据库操作(七))