zoukankan      html  css  js  c++  java
  • 就业培训学习记录-day004

    课堂任务

    视图

    • 视图就是封装了一条复杂的语句
    • 是一个虚表,不占用空间
    • 最大的优点就是简化复杂的查询
    • 视图会限制很多操作,比如说不能使用delete、组函数、group by

    创建视图

    create view empview
    as
    select e.empno,e.ename,e.sal,e.sal*12 ansal,d.dname
    from emp e,dept d
    where e.deptno=d.deptno;
    

    查看视图

    select * from empview;
    

    删除视图

    drop view empview;
    

    序列

    在很多数据库中都存在一个自动增长的列,如果现在要想在oracle中完成自动增长的功能,则只能依靠序列完成。所有的自动增长的操作,需要用户手工完成处理,并且oracle将序列值装入内存可以提高访问效率。
    序列可以多个用户来产生唯一数值的数据库对象、可以自动提供唯一的数值、共享对象、主要用于提供主键值。
    语法:

    CREATE SEQUENCE 序列名
      [INCREMENT BY n]
      [START WITH n]
      [{MAXVALUE/ MINVALUE n| NOMAXVALUE}]
      [{CYCLE|NOCYCLE}]
      [{CACHE n| NOCACHE}];
    

    其中:

    1. INCREMENT BY用于定义序列的步长,如果省略,则默认为1,如果出现负值,则代表Oracle序列的值是按照此步长递减的。
    2. START WITH定义序列的初始值(即产生的第一个值),默认为1。
    3. MAXVALUE定义序列生成器能产生的最大值。选项NOMAXVALUE是默认选项。
    4. MINVALUE定义序列生成器能产生的最小值。
    5. CYCLE和NOCYCLE表示当序列生成器的值达到限制值后是否循环。CYCLE代表循环,NOCYCLE代表不循环。如果循环,则当递增序列达到最大值时,循环到最小值;对于递减序列达到最小值时,循环到最大值。如果不循环,达到限制值后,继续产生新值就会发生错误。
    6. CACHE(缓冲)定义存放序列的内存块的大小,默认为20。NOCACHE表示不对序列进行内存缓冲。对序列进行内存缓冲,可以改善序列的性能。
      大量语句发生请求,申请序列时,为了避免序列在运用层实现序列而引起的性能瓶颈。Oracle序列允许将序列提前生成cache x个先存入内存,在发生大量申请序列语句时,可直接到运行最快的内存中去得到序列。但cache个数也不能设置太大,因为在数据库重启时,会清空内存信息,预存在内存中的序列会丢失,当数据库再次启动后,序列从上次内存中最大的序列号+1 开始存入cache x个。这种情况也能会在数据库关闭时也会导致序号不连续。
    7. NEXTVAL 返回序列中下一个有效的值,任何用户都可以引用。
    8. CURRVAL 获取序列中存放的当前值。首次使用CURRVAL之前,应该先使用一次NEXTVAL。

    下面这个序列的最大值是多少?

    CREATE SEQUENCE dept_deptid_seq
      INCREMENT BY 10
      START WITH 120
      MAXVALUE 9999
      NOCACHE
      NOCYCLE;
    

    答案:9990。因为该序列是从120开始的,每次递增10,则临近最大值9999的序列为9990。

    创建序列

    create sequence myseq;
    

    查看序列

    select myseq.currval from dual;
    

    如果提示“序列 MYSEQ.CURRVAL 尚未在此会话中定义”,则需要先执行一次下面的语句。

    select myseq.nextval from dual;
    

    序列的使用

    首先先创建一张表,然后在这张表做示范

    create table testseq(tid number,tname varchar2(20));
    insert into testseq values(myseq.nextval,'aaaa');
    insert into testseq values(myseq.nextval,'aaaa');
    insert into testseq values(myseq.nextval,'aaaa');
    insert into testseq values(myseq.nextval,'aaaa');
    select * from testseq;
    

    序列可能会产生裂缝的原因

    1. 回滚
    2. 系统异常
    3. 多个表共用一个序列

    删除序列

    drop sequence myseq;
    

    索引

    索引是用于加速数据存取的数据对象,合理的使用索引可以大大降低i/o次数,从而提供数据访问性能。一般来说索引可以提高查询的速度,但不是有了索引,查询速度就一定会提高。
    什么时候创建索引:

    • 列中数据值分布范围很广
    • 列经常在where子句或连接条件中出现
    • 表经常被访问且数据量很大,访问的数据大概占数据总量的2%到4%

    什么时候不要创建索引:

    • 表很小的
    • 列不经常作为链接条件或出现在where子句中
    • 查询的数据大于数据总量的2%到4%
    • 表经常更新

    创建索引

    1. 单列索引
      是基于单个列所建立的索引。
    create index 索引名 on 表名(列名)
    
    1. 复合索引
      是基于两个或多个列的所建立的索引,在同一张表上可以有多个索引,但是要求列的组合必须不同。
    create index 索引名 on 表名(列名1,列名2);
    

    删除索引

    drop index 索引名;
    

    同义词

    同义词就是一个别名,我们给表取一个别名,这个别名就叫同义词。

    create synonym 别名 for 对象(表、视图等);
    

    例如

    create synonym hremp for hr.employees;
    

    PL/SQL

    PLSQL是oracle对sql语言的过程化扩展,在sql命令中增加了过程处理语句(分支,循环),使sql语言具有过程处理能力,把sql语言的数据操纵能力与过程语言的数据处理能力结合起来,使得plsql面向过程但比过程语言简单、高效和灵活。
    plsql结构如下

    DECLARE
    --声明部分,在此声明pl/sql用到的变量,类型及游标,以及局部的存储过程和函数
    BEGIN
    --执行部分,过程及sql语句
    EXCEPTION
    --执行异常
    END;
    

    输出'hello plsql'

    先执行一次下面的语句,打开输出

    set serveroutput on
    

    然后接着开始在命令行使用plsql

    declare
    begin
    dbms_output.put_line('hello plsql');
    end;
    /
    

    SQL> declare
        2    begin
        3    dbms_output.put_line('hello plsql');
        4    end;
        5    /
    hello plsql
    PL/SQL 过程已成功完成。
    已用时间: 00: 00: 00.00

    安装sqldeveloper

    官方下载链接如下,当然也可以自己从其他地方下载。
    Oracle SQL Developer Downloads
    安装教程参考下面的链接,直到可以执行查询语句select * from emp;即可。
    sqldeveloper的安装及其使用教程

    变量

    := 相当于赋值
    定义变量

    Varl char(15);
    Married boolean:=true;
    Psal numbe(7,2);
    My_name emp.ename%type; -- %相当于引用类型,这里的意思是变量My_name的类型就是emp.ename的类型 
    Emp_rec emp%rowtype; -- 记录型变量,相当于行类型,就是引用这一行的类型
    

    引用类型变量

    查询并打印7839的姓名和薪水

    declare
      --定义变量保存姓名和薪水
    --  pename varchar2(25);
    --  psal number;
      pename emp.ename%type;
      psal emp.sal%type;
    begin
      --得到7839的姓名和薪水
      select ename,sal into pename,psal from emp where empno=7839;
      --打印
      dbms_output.put_line(pename||'的薪水是'||psal);
    end;
    

    结果如图,如果没有显示结果,则先执行一次下列语句,再执行上面的语句。

    set serveroutput on
    

    记录类型变量

    查询并打印7566的姓名和薪水

    declare
      --定义记录型变量:代表一行
      emp_rec emp%rowtype;
    begin
      select * into emp_rec from emp where empno=7566;
      dbms_output.put_line(emp_rec.ename||'的薪水是'||emp_rec.sal);
    end;
    

    returning字句

    returning用于检索insert语句中所影响的数据行,当insert语句使用values子句插入数据的时候
    returning子句还可以将插入数据中的某个值返回到输出变量中。

    1. 新增一个99号财务部,地点成都,并显示插入的数据
    declare
      row_id ROWID;
      info varchar2(40);
    BEGIN
      insert into dept values (99,'财务部','成都')
      returning rowid,dname||':'||to_char(deptno)||':'||loc
      into row_id,info;
      dbms_output.put_line('row_id==='||row_id);
      dbms_output.put_line('info==='||info);
      commit;
    end;
    
    1. 把财务部改成90号部门
    declare
      row_id ROWID;
      info varchar2(40);
    begin
      update dept set deptno='90' where dname='财务部'
      Returning rowid,dname||':'||to_char(deptno)||':'||loc into row_id,info;
      DBMS_OUTPUT.PUT_LINE(row_id);
      DBMS_OUTPUT.PUT_LINE(info);
    end;
    

    if条件判断

    语法:

    --写法1
    if 条件1 then 语句1
    end if;
    
    --写法2
    if 条件1 then 语句1;
    else 语句2;
    end if;
    
    --写法3
    if 条件1 then 语句1;
    elsif 条件2 then 语句2;
    else 语句3;
    end if;
    

    判断用户从键盘输入的数字

    declare
      pnum number:=&input;
    begin
      if pnum=0 then DBMS_OUTPUT.PUT_LINE('输入的是0');
      elsif pnum=1 then DBMS_OUTPUT.PUT_LINE('输入的是1');
      elsif pnum=2 then DBMS_OUTPUT.PUT_LINE('输入的是2');
      else DBMS_OUTPUT.PUT_LINE('输入的是其他数字');
      end if;
    end;
    

    循环(for、while)

    语法:

    --写法1
    while 条件
    loop
      语句...
    end loop;
    
    --写法2
    loop
      exit [when 退出条件]; 
      语句...
    end loop;
    
    --写法3
    for i in 1 .. 3
    loop
      语句...
    end loop;
    

    例子

    --写法1
    declare 
      step number:=1;
    begin
      while step<=10
      loop
        DBMS_OUTPUT.PUT_LINE(step);
        step:=step+1;
      end loop;
    end;
    
    --写法2
    declare
      step number:=10;
    begin
      loop
        DBMS_OUTPUT.PUT_LINE(step);
        step:=step+1;
        exit when step>=20;
      end loop;
    end;
    
    --写法3
    declare
      step number;
    begin
      for step in 20..30
      loop
        DBMS_OUTPUT.PUT_LINE(step);
      end loop;
    end;
    

    6道练习题

    这6道题用到的是上述讲过的条件判断和循环。

    1. 输入一个雇员的编号,如果其工资高于3500,则显示高工资,工资大于2000,则显示中等工资
    declare
      eno emp.empno%type;
      psal emp.sal%type;
    begin
      eno:=&seno;
      select sal into psal from emp where empno=eno;
      if psal>3500 then DBMS_OUTPUT.PUT_LINE('高工资');
      elsif psal>2000 and psal<3500 then DBMS_OUTPUT.PUT_LINE('中工资');
      end if;
    end;
    
    1. 输入一个雇员编号,根据它所在的部门涨工资
      10部门上涨10%,20部门上涨20%,30部门上涨30%,其他部门不涨。上涨工资的量不能超过5000,若超过,则涨5000。
    declare
      eno emp.empno%type;
      dno emp.deptno%type;
      esal emp.sal%type;
    begin
      eno:=&eno;
      select deptno,sal into dno,esal from emp where empno=eno;
      if dno=10 then
        esal:=esal*0.1;
      elsif dno=20 then
        esal:=esal*0.2;
      elsif dno=30 then
        esal:=esal*0.3;
      end if;
      if esal>5000 then
        esal:=5000;
      end if;
      update emp set sal=sal+esal where empno=eno;
      commit;
    end;
    
    1. 通过循环,为dept表增增加50~80部门
    declare
      step number:=50;
    begin
      loop
        insert into dept values(step,'财务部','成都');
        step:=step+10;
        exit when step>80;
      end loop;
    end;
    
    1. 输入一个雇员的编号,计算某个雇员的年度薪水总额
    declare
      pnum number:=&num;
      psal number;
    begin
      select empno,sal*12 into pnum,psal from emp where empno=pnum;
      DBMS_OUTPUT.PUT_LINE(pnum||'年薪:'||psal);
    exception
      when no_data_found then
      dbms_output.put_line('没有这个雇员');
    end;
    
    1. 用*打印直接三角形,最大的边是9个*
    begin
      for i in 1 .. 9 loop
        for j in 1 .. i loop
          dbms_output.put('*');
        end loop;
        dbms_output.put_line('');
      end loop;
    end;
    
    1. 打印菱形
    declare
      m number:=4;
    begin
      for y in -m..m loop
        for x in -m..m loop
          if abs(y)+abs(x) <=m then
            dbms_output.put('*');
          else
            dbms_output.put(' ');
          end if;
        end loop;
        dbms_output.put_line('');
      end loop;
    end;
    

    游标

    游标可以存储查询的返回的多条数据。
    语法:

    CURSOR 游标名 [(参数名 数据类型,参数名 数据类型,...)] IS SELECT 语句;
    cursor c1 is select ename from emp;
    

    游标的使用步骤:
    (1) 打开游标:open c1;(打开游标执行查询)
    (2) 取一行游标的值:fetch c1 into pename(取一行到变量中)
    (3) 关闭游标:close c1;(关闭游标释放资源)
    (4) 游标的结束方式:exite when c1%notfound;

    1. 按员工的工种涨工资,总裁涨1000元,经理涨800元,其他涨400元
    declare
      cursor cemp is select empno,job from emp;
      pjob emp.job%type;
      pempno emp.empno%type;
    begin
      --打开游标
      open cemp;
      loop
        --取一个员工
        fetch cemp into pempno,pjob;
        exit when cemp%notfound;
        --判断工种
        if pjob ='PRESIDENT' then update emp set sal=sal+1000 where empno=pempno;
        elsif pjob ='MANAGER' then update emp set sal=sal+800 where empno=pempno;
        else update emp set sal=sal+400 where empno=pempno;
        end if;
      end loop;
      close cemp;
      dbms_output.put_line('完成');
      commit;
    end;
    
    1. 查询并打印员工的姓名和薪水
    declare
      cursor cemp is select ename,sal from emp;
      pename emp.ename%type;
      psal emp.sal%type;
    begin
      open cemp;
      loop
        fetch cemp into pename,psal;
        exit when cemp%notfound;
        dbms_output.put_line(pename||'的薪水是'||psal);
      end loop;
      close cemp;
    end;
    
    1. 带参数的游标,查询某个部门的员工姓名
    declare
      cursor cemp(dno number) is select ename from emp where deptno=dno;
      pename emp.ename%type;
    begin
      --实参
      open cemp(20);
      loop
        fetch cemp into pename;
        exit when cemp%notfound;
        dbms_output.put_line(pename);
      end loop;
      close cemp;
    end;
    

    异常

    异常是程序设计语言提供的一种功能,用来增强程序的健壮性和容错性

    常见异常

    • no_data_found 没有找到数据
    • too_many_rows 行数过多
    • zero_divide 被零除
    • value_error 算术或转换错误
    1. 被零除异常
    declare
      pnum number;
    begin
      pnum:=1/0;
    exception 
      when zero_divide then dbms_output.put_line('0不能做分母');
    end;
    
    1. 自定义异常,查询0号部门的员工
    declare
      cursor cemp is select ename from emp where deptno=0;
      pename emp.ename%type;
      --自定义例外
      no_emp_found exception;
    begin
      open cemp;
      --取第一条记录
      fetch cemp into pename;
      if cemp%notfound then
        --抛出例外
        raise no_emp_found;
      end if;
      close cemp;
    exception
      when no_emp_found then dbms_output.put_line('没有找到员工');
      --其他异常的处理
      when others then dbms_output.put_line('其他异常');
    end;
    

    PL/SQL练习

    1. 统计每年入职的员工个数
      结果应为:1980年1人,1981年10人,1982年1人,1987年2人。
    declare
      --定义游标
      cursor c1 is select to_char(hiredate,'yyyy') from emp; 
      cyear varchar2(4);
      --每年入职的人数
      count80 number:=0;
      count81 number:=0;
      count82 number:=0;
      count87 number:=0;
      total number:=0;
    begin
      --打开游标
      open c1;
      loop
        --取记录
        fetch c1 into cyear;
        exit when c1%notfound;
        --判断年份并做相应处理
        if cyear='1980' then count80:=count80+1;
        elsif cyear='1981' then count81:=count81+1;
        elsif cyear='1982' then count82:=count82+1;
        elsif cyear='1987' then count87:=count87+1;
        end if;
      end loop;
      close c1;
      total:=count80+count81+count82+count87;
      dbms_output.put_line('1980:'||count80);
      dbms_output.put_line('1981:'||count81);  
      dbms_output.put_line('1982:'||count82);
      dbms_output.put_line('1987:'||count87);
      dbms_output.put_line('Total:'||total);
    end;
    
    1. 涨工资
      使用socct用户下的emp表,为员工涨工资。每人涨10%,但是老板规定涨工资的总额只有5万元,也就是说涨工资消耗的总额最多只有5万。请计算并打印最多涨工资的人数和涨工资所消耗的金钱总额。如果涨完某个人之后可涨工资余额不足下一个人,则停止涨工资。多次运行的结果中,涨工资的人数应该越来越少,并且工资总额不应该超过5万。
    declare
      cursor c1 is select empno,sal from emp order by sal;
      cempno emp.empno%type;
      csal emp.sal%type;
      countemp number:=0;
      salTotal number:=0;
    begin
      open c1;
      loop
        --取员工号和当前工资
        fetch c1 into cempno,csal;
        exit when c1%notfound;
        --如果涨工资后所需的金额不超过5万
        if salTotal+csal*1.1<50000 then
          update emp set sal=sal*1.1 where empno=cempno;
          countemp:=countemp+1;
          salTotal:=salTotal+csal*1.1;
        --如果超过,则退出循环
        else exit;
        end if; 
      end loop;
      dbms_output.put_line('countemp:'||countemp);
      dbms_output.put_line('salTotal:'||salTotal);
    end;
    
    1. 按部门和薪水进行分段统计
      按照部门和不同阶段的薪水(6000以上,(6000~3000),3000以下),统计各个工资段的职工人数,以及各部门的工资总额。将结果插入到一张新表中,表的结构如下。
    --建表语句
    CREATE TABLE MSG(DEPTNO NUMBER,NUM1 NUMBER,NUM2 NUMBER,NUM3 NUMBER,SUM_SAL NUMBER);
    
    部门 小于3000 3000~6000 大于6000 工资总额
    10
    20
    30
    40
    ...
    declare
      cursor c1 is select deptno from dept;
      cdeptno dept.deptno%type;
      cursor c2(input number) is select sal from emp where deptno=input;
      csal emp.sal%type;
      count3k number:=0;
      count3kto6k number:=0;
      count6k number:=0;
      sumsal number:=0;
    begin
      open c1;
      loop
        fetch c1 into cdeptno;
        exit when c1%notfound;
        count3k:=0;
        count3kto6k:=0;
        count6k:=0;
        select sum(sal) into sumsal from emp where deptno=cdeptno;
        open c2(cdeptno);
        loop
          fetch c2 into csal;
          exit when c2%notfound;
          if csal<3000 then count3k:=count3k+1;
          elsif csal between 3000 and 6000 then count3kto6k:=count3kto6k+1;
          else count6k:=count6k+1;
          end if;
        end loop;
        close c2;
        insert into msg values(cdeptno,count3k,count3kto6k,count6k,sumsal);
      end loop;
      close c1;
      commit;
      dbms_output.put_line('完成');
    end;
    

    课后任务

    使用scott用户完成以下练习

    1. 选择30号部门员工的所有信息
    select * from emp where deptno=30;
    
    1. 列出职位为MANAGER的员工编号、姓名
    select empno,ename from emp where job='MANAGER';
    
    1. 找出奖金高于工资的员工
    select * from emp where nvl(comm,0)>sal;
    
    1. 找出每个员工奖金和工资的总和
    select empno,ename,sal,comm,sal+nvl(comm,0) as sum from emp;
    
    1. 找出10号部门中既不是经理也不是普通员工,而且工资大于等于2000的员工
    select * from emp where deptno=10 and job not in('MANAGER','CLERK') and sal>=2000;
    
    1. 找出有奖金的员工的不同工作
    select distinct job from emp where comm is not null;
    
    1. 找出没有奖金或者奖金低于500的员工
    select * from emp where nvl(comm,0)<500;
    
    1. 显示雇员姓名,根据其服务年限,将最老的雇员排在最前面
    select ename,hiredate from emp order by HIREDATE asc;
    
    1. 找出每个月倒数三天受雇的员工(如:2009-5-29)
    select * from emp where hiredate=last_day(hiredate)-2;
    
    1. 找出25年雇的员工
    select * from emp where to_char(sysdate,'yyyy')-to_char(hiredate,'yyyy')>25;
    
    1. 所有员工名字前加上Dear,并且名字首字母大写
    select 'Dear'||initcap(ename) from emp;
    
    1. 找出姓名为5个字母的员工
    select * from emp where ename like '_____';
    
    1. 找出姓名中不带R这个字母的员工
    select * from emp where ename not like '%R%';
    
    1. 显示所有员工姓名的第一个字母
    select empno,substr(ename,1,1),job,mgr,hiredate,sal,comm,deptno from emp;
    
    1. 分组统计各部门下工资>500的员工的平均工资
    select deptno,avg(sal) from emp where sal>500 group by deptno;
    
    1. 统计各部门下平均工资大于500的部门
    select deptno,avg(sal) from emp group by deptno having avg(sal)>500;
    
    1. 算出30号部门中得到最多奖金的员工姓名
    select ename,comm from emp where comm=(select max(comm) from emp where deptno=30);
    
    1. 算出每个职位的员工数和最低工资
    select job,count(*),min(sal) from emp group by job;
    
    1. 算出每个部门、每个职位的平均工资和平均奖金(平均奖金包括没有奖金),如果平均奖金大于300,显示“奖金不错”,如果平均奖金在100到300之间,显示“奖金一般”,如果平均奖金小于100,显示“基本没有奖金”,按部门编号降序,平均工资降序排列
    select deptno,job,avg(sal),avg(nvl(comm,0)),
      decode(trunc(avg(nvl(comm,0))/100),
      '0','基本没有奖金',
      '1','奖金一般',
      '2','奖金一般',
      '奖金不错')
    from emp
    group by deptno,job
    order by deptno,avg(sal) desc;
    
    1. 列出员工表中每个部门的员工数和部门号
    select deptno,count(*) from emp group by deptno;
    
    1. 查出工资大于自己部门平均工资的员工信息
    select a.*,b.avgsal
    from emp a,(
      select deptno,avg(sal) as avgsal from emp group by deptno
    ) b 
    where a.sal>b.avgsal and a.deptno=b.deptno;
    
    1. 分组统计每个部门、每种职位的平均奖金(也要算没奖金的人)和总工资(包括奖金)
    select deptno,job,avg(nvl(comm,0)),sum(nvl(comm,0))+sum(sal)
    from emp
    group by deptno,job;
    
    1. 列出员工表中每个部门的员工数(员工数必须大于3)和部门名称
    select e.deptno,d.dname,count(*)
    from emp e left join dept d on e.deptno=d.deptno
    group by e.deptno,d.dname
    having count(*)>3;
    
    1. 找出工资比JONES多的员工
    select * from emp where sal>(select sal from emp where ename='JONES');
    
    1. 列出所有员工的姓名及其上级的姓名
    select a.ename,b.ename from emp a left join emp b on a.mgr=b.empno;
    
    1. 以职位分组,找出平均工资最高的两种职位
    select job,avgsal
    from (
      select job,avg(sal) as avgsal from emp group by job order by avg(sal) desc
    )
    where rownum<=2;
    
    1. 查找出不在20号部门,并且比20号部门任何一个人工资都高的员工姓名和部门名称
    select e.ename,d.dname
    from emp e left join dept d on e.deptno=d.deptno
    where e.deptno!=20 and sal>(select max(sal) from emp where deptno=20);
    
    1. 查出平均工资大于2000的职位
    select job,avg(sal) from emp group by job having avg(sal)>2000;
    
    1. 分部门得到工资大于2000的员工的平均工资,并且平均工资还要大于2500
    select deptno,avg(sal) from emp where sal>2000 group by deptno having avg(sal)>2500;
    
    1. 查出每个月工资总数最少的部门的部门编号、名称和位置
    select distinct e.deptno,d.dname,d.loc
    from emp e left join dept d on e.deptno=d.deptno
    where e.deptno=(
      select deptno from (
        select deptno,sum(sal) as sumsal
        from emp
        group by deptno
        order by sumsal asc
      )
    where rownum=1
    );
    
    1. 分部门查询平均工资等级为2级(见工资等级表)的部门编号
    select distinct deptno
    from emp e,salgrade s
    where grade=2 and e.sal between s.losal and s.hisal;
    
    1. 查出收入(工资加奖金),下级比自己上级还高的员工编号、姓名和收入
    select a.empno,a.ename,a.sal+nvl(a.comm,0)
    from emp a left join emp b on a.mgr=b.empno
    where a.sal+nvl(a.comm,0)>b.sal+nvl(b.comm,0);
    
    1. 查出工资等级不为4级的员工的姓名、部门名字和部门位置
    select e.ename,d.dname,d.loc,e.sal
    from emp e,salgrade s,dept d
    where e.deptno=d.deptno and grade!=4 and e.sal between s.losal and s.hisal;
    
    1. 查出职位和 MARTIN 或者 SMITH 一样的员工的平均工资
    select avg(sal)
    from emp
    where job in (select job from emp where ename in ('MARTIN','SMITH'));
    
    1. 查找出不属于任何部门的员工
    select * from emp where deptno is null;
    
    1. 按部门统计员工数,查出员工数最多的部门的第二名到第五名(列出部门名字和位置)
    select dname,loc
    from (
      select rownum row_num,deptno
      from (
        select count(*) count_emp,deptno
        from emp
        group by deptno
        order by count_emp desc
      )
    ) e,dept d 
    where e.row_num between 2 and 5 and e.deptno=d.deptno;
    
    1. 查询出 KING 所在的部门号、部门名称和部门人数
    select e.count_num,d.dname,d.loc
    from dept d,(
      select count(*) count_num,deptno
      from emp
      where deptno=(
        select deptno
        from emp
        where ename='KING'
      )
      group by deptno
    )e
    where d.deptno=e.deptno;
    
    1. 查询出工资成本最高的部门的部门号和名称
    select d.deptno,d.dname,t.sumsal
    from dept d,(
      select deptno,sum(sal) sumsal
      from emp
      group by deptno
      having sum(sal)=(
        select max(sum(sal))
        from emp
        group by deptno
      )
    ) t
    where d.deptno=t.deptno;
    

    建表完成以下练习

    DROP TABLE IF EXISTS student;
    DROP TABLE IF EXISTS teacher;
    DROP TABLE IF EXISTS course;
    DROP TABLE IF EXISTS choose_course;
    create table student(sid number,sname varchar2(20));
    create table teacher(tid number,tname varchar2(20));
    create table course(cid number,cname varchar2(20),ctype varchar2(20));
    create table choose_course(ccid number,sid number,tid number,cid number);
    insert into student values(1,'小明');
    insert into student values(2,'小花');
    insert into teacher values(1,'陈红');
    insert into teacher values(2,'陈白');
    insert into course values(1,'语文','文科');
    insert into course values(1,'数学','理科');
    -- 小明选了陈红老师的语文
    insert into choose_course values(1,1,1,1);
    -- 小明选了陈红老师的数学
    insert into choose_course values(2,1,1,2);
    -- 小花选了陈红老师的数学
    insert into choose_course values(3,2,1,2);
    -- 小明选了陈白老师的语文
    insert into choose_course values(1,1,2,1);
    -- 小花选了陈红老师的语文
    insert into choose_course values(4,2,1,1);
    
    1. 查找陈红老师教的学生有哪些
    select distinct s.sname from student s,teacher t,choose_course cc
    where s.sid=cc.sid and t.tid=cc.tid and t.tname='陈红';
    
    1. 找出学生小明所有的文科老师
    select tname
    from student s,choose_course cc,teacher t,course c
    where s.sid=cc.sid and cc.tid=t.tid and cc.cid=c.cid and s.sname='小明' and c.ctype='文科';
    select s.sname
    
    1. 查出没有选陈红老师的课的学生
    select s.sname
    from student s
    minus
    select s.sname
    from student s,teacher t,choose_course cc
    where s.sid=cc.sid and t.tid=cc.tid and t.tname='陈红';
    
    1. 查出教的学生最少的老师
    select tname
    from teacher
    where tid=(
      select tid from (
        select count(*) as count_num,tid from (
          select distinct sid,tid from choose_course
        )
        group by tid
        order by count_num asc
      )
      where rownum=1
    );
    
  • 相关阅读:
    server2012/win8 卸载.net framework 4.5后 无法进入系统桌面故障解决【转】
    Entity Framework中AutoDetectChangesEnabled為false時更新DB方法
    git常用命令备忘录
    MSSQL日誌傳輸熱備份注意事項
    c#生成唯一编号方法记录,可用数据库主键 唯一+有序
    Angular 隨記
    使用dumpbin命令查看dll导出函数及重定向输出到文件【轉】
    UML类图与类的关系详解【转】
    知識隨記
    session不会过期
  • 原文地址:https://www.cnblogs.com/ast935478677/p/14689118.html
Copyright © 2011-2022 走看看