• Oracle游标总结三


    -- 声明游标;CURSOR cursor_name IS select_statement

    --For 循环游标
    --(1)定义游标
    --(2)定义游标变量
    --(3)使用for循环来使用这个游标,for循环时
    declare 
      cursor c_job
      is
      select empno,ename,job,sal from emp
      where job='MANAGER';
      c_row c_job%rowtype;
    begin
      open c_job;
        for c_row in c_job loop
            dbms_output.put_line(c_row.empno||c_row.ename)
        end loop;
      close c_job;
    end
    --Fetch游标
    --使用的时候必须要明确的打开和关闭
    declare
      cursor c_job
      is 
      select empno,ename from emp
      where job='MANAGER';
      c_row c_job%rowtype;
    begin
      open c_job;
         loop
           fetch c_job into c_row;
           --判读是否提取到值,没取到值就退出
           --取到值c_job%notfound 是false 
           --取不到值c_job%notfound 是true
           exit when c_job%notfound;
          end loop
       close c_job;
    end;
    --1:任意执行一个update操作,用隐式游标sql的属性%found,%notfound,%rowcount,%isopen观察update语句的执行情况。
    begin
        update emp set ENAME='ALEARK' WHERE EMPNO=7469;
        if sql%isopen then
            dbms_output.put_line('Openging');
        else
            dbms_output.put_line('closing');
        end if;
        if sql%found then
            dbms_output.put_line('游标指向了有效行');--判断游标是否指向有效行
        else
            dbms_output.put_line('Sorry');
        end if;
        if sql%notfound then
            dbms_output.put_line('Also Sorry');
        else
            dbms_output.put_line('Haha');
        end if;
            dbms_output.put_line(sql%rowcount);
        exception 
        when no_data_found then
            dbms_output.put_line('Sorry No data');
        when too_many_rows then
            dbms_output.put_line('Too Many rows');
    end;
    declare
        empNumber emp.EMPNO%TYPE;
        empName emp.ENAME%TYPE;
    begin
        if sql%isopen then
            dbms_output.put_line('Cursor is opinging');
        else
            dbms_output.put_line('Cursor is Close');
        end if;
        if sql%notfound then
            dbms_output.put_line('No Value');
        else
            dbms_output.put_line(empNumber);
        end if;
            dbms_output.put_line(sql%rowcount);
            dbms_output.put_line('-------------');
    
            select EMPNO,ENAME into  empNumber,empName from emp where EMPNO=7499;
            dbms_output.put_line(sql%rowcount);
    
        if sql%isopen then
            dbms_output.put_line('Cursor is opinging');
        else
            dbms_output.put_line('Cursor is Closing');
        end if;
        if sql%notfound then
            dbms_output.put_line('No Value');
        else
            dbms_output.put_line(empNumber);
        end if;
        exception 
        when no_data_found then
            dbms_output.put_line('No Value');
        when too_many_rows then
            dbms_output.put_line('too many rows');
    end;
    --2,使用游标和loop循环来显示所有部门的名称
    --游标声明
    declare
       cursor csr_dept
       is
       select dname from depth;
       row_dept csr_dept%rowtype;
    begin
       for row_dept in csr_dept loop
           dbms_output.put_line(row_dept.dname);
       end loop;
    end;
    --3,使用游标和while循环来显示所有部门的的地理位置(用%found属性)
    declare
       cursor csr_TestWhile
       is 
       select LOC from Depth;
       row_loc csr_TestWhile%rowtype;
    begin
       open csr_TestWhile;
       --必须先fetch一遍,才能进行%found判断,否则一直都是空为false
       fetch csr_TestWhle into row_loc;
         while csr_TestWhile%found loop
           dbms_output.put_line(row_loc.LOC);
           fetch csr_TestWhile into row_loc;
         end loop;
         close csr_TestWhile;
    end
    --4,接收用户输入的部门编号,用for循环和游标,打印出此部门的所有雇员的所有信息(使用循环游标)
    --CURSOR cursor_name[(parameter[,parameter],...)] IS select_statement;
    --定义参数的语法如下:Parameter_name [IN] data_type[{:=|DEFAULT} value]
    declare
     --定义带参数的游标
     cursor c_dept(p_deptNo number)
     is
     select * from emp where emp.depno=p_deptNo;
     r_emp emp%rowtype;
    begin
      --遍历游标,调用游标传参数
      for r_emp in c_dept(20) loop
        dbms_output.put_line('员工号:'||r_emp.EMPNO||'员工名:'||r_emp.ENAME||'工资:'||r_emp.SAL);
      end loop;
    end;
    --6:用更新游标来为雇员加佣金:(用if实现,创建一个与emp表一摸一样的emp1表,对emp1表进行修改操作),并将更新前后的数据输出出来 
           create table emp1 as select * from emp;
            
    declare
            cursor
            csr_Update
            is
            select * from  emp1 for update OF SAL;
            empInfo csr_Update%rowtype;
            saleInfo  emp1.SAL%TYPE;
    begin
        FOR empInfo IN csr_Update LOOP
          IF empInfo.SAL<1500 THEN
            saleInfo:=empInfo.SAL*1.2;
           elsif empInfo.SAL<2000 THEN
            saleInfo:=empInfo.SAL*1.5;
            elsif empInfo.SAL<3000 THEN
            saleInfo:=empInfo.SAL*2;
          END IF;
          UPDATE emp1 SET SAL=saleInfo WHERE CURRENT OF csr_Update;
         END LOOP;
    END;

    --7:编写一个PL/SQL程序块,对名字以‘A’或‘S’开始的所有雇员按他们的基本薪水(sal)的10%给他们加薪(对emp1表进行修改操作)
    declare
       cursor csr_addSal
       is select sal from emp where ename like 'A%' or ename like'S%';
       r_addSal csr_addSal%rowtype;
       saleInfo emp.sal%type;
    begin
      for r_addSal in csr_addSal loop
          saleInfo := r_addSal.sal*1.1;
          update emp set sal = saleInfo where ename like 'A%' or ename like'S%';  
      end loop;
    end
    --8:编写一个PL/SQL程序块,对所有雇员按他们的基本薪水(sal)的20%为他们加薪,
    --如果增加的薪水大于300就取消加薪(对emp1表进行修改操作,并将更新前后的数据输出出来)
    declare 
     cursor
      crs_UpadateSal
      is select sal from emp;
      r_UpadateSal crs_UpadateSal%rowtype
      salAdd emp.sal%type;
      salInfo emp.sal%type;
    begin
      for r_UpadateSal in crs_UpadateSal loop
        salAdd:=r_UpadateSal.sal*0.2;
        if salAdd>300 then
           salInfo:=r_r_UpadateSal.sal;
        else 
           salInfo:=r_UpadateSal.sal+salAdd;
          end if
         update emp set sal=salInfo where current of crs_UpadateSal;
        end loop;
    end;
    --9:将每位员工工作了多少年零多少月零多少天输出出来   
    --近似
    --CEIL(n)函数:取大于等于数值n的最小整数
    --FLOOR(n)函数:取小于等于数值n的最大整数
    --truc的用法 http://publish.it168.com/2005/1028/20051028034101.shtml
    declare
        cursor
          crs_workDay
          is select ename,hirdate,trunc(months_between(sysdate,hirdate)/12) as years,
          trunc(mod(months_between(sysdate,hirdate),12)) as monthss,
          trunc(mod(sysdate-hirdate),365),12) as days
          from emp
          r_workDay crs_workDay%rowtype;
    begin
      for r_workDay in crs_workDay loop
        dbms_output.put_line(r_WorkDay.ENAME||'已经工作了'||r_WorkDay.SPANDYEARS||'年,零'||r_WorkDay.months||'月,零'||r_WorkDay.days||'');
        end loop;
    end
    --10:输入部门编号,按照下列加薪比例执行(用CASE实现,创建一个emp1表,修改emp1表的数据),并将更新前后的数据输出出来
    -- deptno raise(%)
    -- 10 5%
    -- 20 10%
    -- 30 15%
    -- 40 20%
    -- 加薪比例以现有的sal为标准
    --CASE expr WHEN comparison_expr THEN return_expr
    --[, WHEN comparison_expr THEN return_expr]... [ELSE else_expr] END
    declare
     cursor 
      crs_caseTest
      is select deptNo,sal from emp;
      r_caseTest crs_caseTest%rowtype;
      salInfo emp.sal%rowtype;
    begin
      for r_caseTest in crs_caseTest loop
          case 
            when r_caseTest.deptNo=10 then
            salInfo = r_caseTest.sal*1.05;
            when r_caseTest.deptNo=10 then
            salInfo = r_caseTest.sal*1.1;
            when r_caseTest.deptNo=10 then
            salInfo = r_caseTest.sal*1.15;
            when r_caseTest.deptNo=10 then
            salInfo = r_caseTest.sal*1.2;
           end case;
           update emp set sal = salInfo where current of crs_caseTest;
      end loop;
    end;
    --13:对每位员工的薪水进行判断,如果该员工薪水高于其所在部门的平均薪水,则将其薪水减50元,输出更新前后的薪水,员工姓名,所在部门编号。
    --AVG([distinct|all] expr) over (analytic_clause)
    ---作用:
    --按照analytic_clause中的规则求分组平均值。
    --分析函数语法:
    --FUNCTION_NAME(<argument>,<argument>...)
    --OVER
    --(<Partition-Clause><Order-by-Clause><Windowing Clause>)
    --PARTITION子句
    --按照表达式分区(就是分组),如果省略了分区子句,则全部的结果集被看作是一个单一的组
    DECLARE
     cursor csr_agvSal
     is select empno,sal,avg(sal) over (parition by deptno) as avgSal from emp;
     r_avgSal csr_agvSal%rowtype;
     salInfo emp.sal%type;
    begin
      for r_avgSal in csr_agvSal loop
          if r_avgSal.sal>r_avgSal.avgSal then
             salInfo := r_avgSal.sal-50;
            end if;
            update emp set sal = salInfo where current of csr_agvSal;
      end loop;
    end;


  • 相关阅读:
    ArcMAP操作 获取点所在栅格的高程值
    AE代码 积累
    AE 判断点是否在面内
    ArcMAP获取要素的外包多边形
    DEM消除平三角形教程
    博文目录
    Redis哨兵集群部署
    引用-各类数据库整体架构图汇总
    百度数仓Palo-Doris并发压测性能
    引用-Phoenix介绍
  • 原文地址:https://www.cnblogs.com/tingbogiu/p/5715759.html
Copyright © 2020-2023  润新知