Oracle 游标的练习

--1、什么是游标?使用游标的基本步骤是什么? 
/*
挡在PL/SQL块中执行查询语句(SELECT)和数据操纵语句(DML)时,
Oracle会在内存中分配一个缓冲区,缓冲区中包含了处理过程的必需信息,
包括已经处理完的行数、指向被分析行的指针和查询情况下的活动集,即查询语句返回的数据行集。
该缓冲区域称为上下文区,游标是指向该缓冲区的句柄或指针。
*/


--2、游标有哪几种类型?分别在什么情况下使用? 
/*
(1)显式游标:由用户定义、操作,用于处理返回多行数据的SELECT查询。
(2)隐式游标:由系统自动进行操作,用于处理DML语句和返回单行数据的SELECT查询。
*/


--3、用游标显示所有部门编号与名称,以及其所拥有的员工人数。
--方法一
declare
  cursor c_emp is select * from emp;
  cursor c_dept is select * from dept;
  v_count number;
begin
  for v_dept in c_dept loop
    v_count := 0;
    for v_emp in c_emp loop
      if v_emp.deptno = v_dept.deptno then
        v_count := v_count + 1;
      end if;
    end loop;
    dbms_output.put_line('编号:' || v_dept.deptno || '是:' || 
                        v_dept.dname || '部门,共有员工' || v_count || '人。');
  end loop;
end;
--方法二:(PS:缺失没有员工的部门)
declare
  cursor c_temp is (select deptno, dname, count(*) count_p
  from (select d.deptno, d.dname
          from dept d
          join emp e on d.deptno = e.deptno) t
 group by deptno, dname);
begin
  for v_temp in c_temp loop
    dbms_output.put_line(v_temp.deptno || '-' || v_temp.dname || '-' || v_temp.count_p);
  end loop;
end;


--4、用游标属性%rowcount实现输出前十个员工的信息。
declare
  cursor c is (select * from emp);
begin
  for v in c loop
    if c%rowcount<=10 then
      dbms_output.put_line(c%rowcount || '-' || v.empno || '-' || v.ename || '-' || v.sal);
    else exit;
    end if;
  end loop;
end;


--5、通过使用游标来显示dept表中的部门名称,及其相应的员工列表(提示:可以使用双重循环)。
declare
  cursor c_emp is select * from emp;
  cursor c_dept is select * from dept;
begin
  for v_dept in c_dept loop
    dbms_output.put_line( v_dept.dname || ' 部门人员列表:');
    for v_emp in c_emp loop
      if v_emp.deptno = v_dept.deptno then
        dbms_output.put_line('    ' || v_emp.ename);
      end if;
    end loop;
    dbms_output.put_line('');
  end loop;
end;


--6、接受一个部门号,使用For循环,从emp表中显示该部门的所有雇员的姓名,工作和薪水。
declare
  cursor c_emp is select * from emp where deptno = &please_enter_deptno;
  v_dept dept%rowtype;
begin
  select * into v_dept from dept where  deptno = &please_enter_deptno;
  dbms_output.put_line(&please_enter_deptno || ' :: ' || v_dept.dname);
  dbms_output.put_line('');
  dbms_output.put_line('ename :: job :: sal');
  for v_emp in c_emp loop
    dbms_output.put_line(v_emp.ename || ' :: ' || v_emp.job || ' :: ' || v_emp.sal);
  end loop;
end;


--7、编写一个程序块,将emp表中前5人的名字,及其出的工资等级(salgrade)显示出来。
begin
  for v_emp in (select e.ename, s.grade
  from emp e
  join salgrade s on e.sal between s.losal and s.hisal where rownum < =5) loop
    dbms_output.put_line(v_emp.ename || ' :: grade ' || v_emp.grade);
  end loop;
end;


--8、用带参数的游标输出部门编号为10, 30的员工信息。
declare
  cursor c_emp(v_deptno dept.deptno%type) is select * from emp where deptno = v_deptno;
begin
  dbms_output.put_line('部门编号为:10 的员工列表');
  for v_emp in c_emp(10) loop
    dbms_output.put_line(v_emp.ename);
  end loop;
  dbms_output.put_line('部门编号为:30 的员工列表');
  for v_emp in c_emp(30) loop
    dbms_output.put_line(v_emp.ename);
  end loop;
end;


--9、使用带参数的游标,实现接受一个部门名称,从emp表中显示该部门的所有雇员的姓名,工作和薪水。
declare
  cursor c_emp(v_dname dept.dname%type) is select * from emp where deptno = (select deptno from dept where dname = v_dname);
begin
  dbms_output.put_line('SALES 部门员工名单:');
  for v_emp in c_emp('SALES') loop
    dbms_output.put_line(v_emp.ename || ' :: ' || v_emp.job || ' :: ' || v_emp.sal);
  end loop;
end;


--10、用游标获取所有收入超过2000的 salesman.
declare
  cursor c_emp is select * from emp;
begin
  dbms_output.put_line('收入超过1500的SALESMAN列表:');
  --收入超过2000的salesman没有数据
  for v_emp in c_emp loop
    if v_emp.job = 'SALESMAN' and v_emp.sal > 1500 then
      dbms_output.put_line(v_emp.ename || ' :: ' || v_emp.sal);
    end if;
  end loop;
end;


--11、编写一个PL/SQL程序块,从emp表中对名字以"A"或"S"开始的所有雇员按他们基本薪水的10%给他们加薪。
declare
  cursor c_emp is select * from emp2 for update;
begin
  for v_emp in c_emp loop
    if substr(v_emp.ename,1,1) = 'A' or substr(v_emp.ename,1,1) = 'S' then
      dbms_output.put_line('加薪员工:' || v_emp.ename || '加薪:' || v_emp.sal*0.1);
      update emp2 set sal = sal*1.1 where ename = v_emp.ename;
    end if;
  end loop;
  commit;
end;


--12、emp表中对所有雇员按他们基本薪水的10%给他们加薪,如果所增加后的薪水大于5000,则取消加薪。
begin
  for v_emp in (select ename,sal,empno from emp2) loop
    if v_emp.sal*1.1 < 5000 then
      dbms_output.put_line('待加薪的员工:' || v_emp.ename);
      update emp2 set sal = sal * 1.1 where empno = v_emp.empno;
    end if;
  end loop;
  commit;
end;


--13、按照salgrade表中的标准,给员工加薪,1:5%,2:4%,3:3%,4:2%,5:1%, 
--并打印输出每个人,加薪前后的工资。
--方法一
declare
  cursor c_emp is(
    select ename, sal, grade
      from emp2 e
      join salgrade s on e.sal between s.losal and s.hisal) order by ename;
begin
  for v_emp in c_emp loop
    update emp2 set sal = sal * (1+((6 - v_emp.grade)*0.01)) where emp2.ename = v_emp.ename;
    dbms_output.put_line(v_emp.ename || ',加薪前:' || v_emp.sal || ',等级:' || 
                         v_emp.grade || ',加薪后:' || v_emp.sal * (1+((6 - v_emp.grade)*0.01)));
  end loop;
  commit;
end;
--方法二
declare
  cursor c_emp is(
    select ename, sal, grade
      from emp2 e
      join salgrade s on e.sal between s.losal and s.hisal) order by ename;
begin
  for v_emp in c_emp loop
    case v_emp.grade
    when 1 then
      update emp2 set sal = sal * (1+0.05) where emp2.ename = v_emp.ename;
    when 2 then
      update emp2 set sal = sal * (1+0.04) where emp2.ename = v_emp.ename;
    when 3 then
      update emp2 set sal = sal * (1+0.03) where emp2.ename = v_emp.ename;
    when 4 then
      update emp2 set sal = sal * (1+0.02) where emp2.ename = v_emp.ename;
    when 5 then
      update emp2 set sal = sal * (1+0.01) where emp2.ename = v_emp.ename;
    else null;
    end case;
    
    /*dbms_output.put_line(v_emp.ename || ',加薪前:' || v_emp.sal || ',等级:' || 
                         v_emp.grade || ',加薪后:' || v_emp.sal * (1+((6 - v_emp.grade)*0.01)));*/
  end loop;
  commit;
end;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

于大大大洋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值