• PL/SQL学习笔记_02_游标


            在 PL/SQL 程序中,对于处理多行记录的事务经常使用游标来实现。 

           为了处理 SQL 语句, ORACLE 必须分配一片叫上下文( context area )的区域来处理所必需的信息,其中包括要处理的行的数目,一个指向语句被分析以后的表示形式的指针以及查询的活动集(active set)。

           游标是一个指向上下文的句柄( handle)或指针。通过游标, PL/SQL 可以控制上下文区和处理语句时上下文区会发生些什么事情。

    1.处理显示游标

    处理显示游标有4个步骤:

    (1)定义游标:

    CURSOR   cursor_name  [(parameter [, parameter]…) ]   IS   子查询 ;

    在指定数据类型时,不能使用长度约束。如 NUMBER(4)CHAR(10) 等都是错误的。

    (2)打开游标:

    OPEN  cursor_name  [([parameter =>] value [, [parameter =>] value]…)];

            就是执行游标所对应的 SELECT 语句,将其查询结果放入工作区,并且指针指向工作区的首部,标识游标结果集合。如果游标查询语句中带有 FOR UPDATE 选项, OPEN 语句还将锁定数据库表中游标结果集合对应的数据行。 

    (3)提取游标数据: 

    FETCH  cursor_name  INTO  { variable_list | record_variable };

             检索结果集合中的数据行,放入指定的输出变量中。

    对该记录进行处理;
    继续处理,直到活动集合中没有记录;

    (4)关闭游标:  

    CLOSE  cursor_name;

           当提取和处理完游标结果集合数据后,应及时关闭游标,以释放该游标所占用的系统资源,并使该游标的工作区变成无效,不能再使用 FETCH 语句取其中数据。

           关闭后的游标可以使用 OPEN 语,句重新打开。 

    注:定义的游标不能有 INTO 子句

    示例1:

    declare
      --1. 定义游标
      cursor salary_cursor is select salary from employees where department_id = 80;
      v_salary employees.salary%type;
    begin
     --2. 打开游标
     open salary_cursor;
    
     --3. 提取游标
     fetch salary_cursor into v_salary;
     
     --4. 对游标进行循环操作: 判断游标中是否有下一条记录
    while salary_cursor%found loop
          dbms_output.put_line('salary: ' || v_salary);
          fetch salary_cursor into v_salary;
    end loop;  
     
     --5. 关闭游标
     close  salary_cursor;
    end;

    示例2:

    /*
    利用游标, 调整公司中员工的工资: 
        
        工资范围       调整基数
        0 - 5000       5%
        5000 - 10000   3%
        10000 - 15000  2%
        15000 -        1%
    */
    declare
        --定义游标
        cursor emp_sal_cursor is select salary, employee_id from employees;
        
        --定义基数变量
        temp number(4, 2);
        
        --定义存放游标值的变量
        v_sal employees.salary%type;
        v_id employees.employee_id%type;
    begin
        --打开游标
        open emp_sal_cursor;
        
        --提取游标
        fetch emp_sal_cursor into v_sal, v_id;
        
        --处理游标的循环操作
        while emp_sal_cursor%found loop
              --判断员工的工资, 执行 update 操作
              --dbms_output.put_line(v_id || ': ' || v_sal);
                
              if v_sal <= 5000 then
                 temp := 0.05;
              elsif v_sal<= 10000 then
                 temp := 0.03;   
              elsif v_sal <= 15000 then
                 temp := 0.02;
              else
                 temp := 0.01;
              end if;
              
              --dbms_output.put_line(v_id || ': ' || v_sal || ', ' || temp);
              update employees set salary = salary * (1 + temp) where employee_id = v_id; 
                      
              fetch emp_sal_cursor into v_sal, v_id;
        end loop;
        --关闭游标
        close emp_sal_cursor;
    end;

      使用SQL中的 decode 函数

      update employees set salary = salary * (1 + (decode(trunc(salary/5000), 0, 0.05,
      1, 0.03,
      2, 0.02,
      0.01)))

    2.游标属性


    %FOUND
    布尔型属性,当最近一次读记录时成功返回,则值为 TRUE
    %NOTFOUND 布尔型属性,与%FOUND 相反;
    %ISOPEN 布尔型属性,当游标已打开时返回 TRUE
    %ROWCOUNT 数字型属性,返回已从游标中读取的记录数。

    3. 游标的 FOR 循环

    FOR index_variable  IN  cursor_name[value[, value]…]  LOOP
        -- 游标数据处理代码
    END LOOP;

     PL/SQL 语言提供了游标 FOR 循环语句,自动执行游标的 OPENFETCHCLOSE 语句和循环语句的功能

     如果在游标查询语句的选择列表中存在计算列,则必须为这些计算列指定别名后才能通过游标 FOR 循环语句中的索引变量来访问这些列数据

     注:不要在程序中对游标进行人工操作;不要在程序中定义用于控制 FOR 循环

    示例1:

    /*
     利用游标, 调整公司中员工的工资: 
        
        工资范围       调整基数
        0 - 5000       5%
        5000 - 10000   3%
        10000 - 15000  2%
        15000 -        1%
    */
    declare
        --定义游标
        cursor emp_sal_cursor is select salary, employee_id id from employees;
        
        --定义基数变量
        temp number(4, 2);
    begin
        --处理游标的循环操作
        for c in emp_sal_cursor loop
              --判断员工的工资, 执行 update 操作
              --dbms_output.put_line(v_id || ': ' || v_sal);
                
              if c.salary <= 5000 then
                 temp := 0.05;
              elsif c.salary <= 10000 then
                 temp := 0.03;   
              elsif c.salary <= 15000 then
                 temp := 0.02;
              else
                 temp := 0.01;
              end if;
              
              --dbms_output.put_line(v_id || ': ' || v_sal || ', ' || temp);
              update employees set salary = salary * (1 + temp) where employee_id = c.id;
        end loop;
    end;

    4.带参数的游标

    declare
        --定义游标
        cursor emp_sal_cursor(dept_id number, sal number) is 
               select salary + 1000 sal, employee_id id 
               from employees 
               where department_id = dept_id and salary > sal;
        
        --定义基数变量
        temp number(4, 2);
    begin
        --处理游标的循环操作
        for c in emp_sal_cursor(sal => 4000, dept_id => 80) loop
              --判断员工的工资, 执行 update 操作
              --dbms_output.put_line(c.id || ': ' || c.sal);
              
              if c.sal <= 5000 then
                 temp := 0.05;
              elsif c.sal <= 10000 then
                 temp := 0.03;   
              elsif c.sal <= 15000 then
                 temp := 0.02;
              else
                 temp := 0.01;
              end if;
              
              dbms_output.put_line(c.sal || ': ' || c.id || ', ' || temp);
              --update employees set salary = salary * (1 + temp) where employee_id = c.id;
        end loop;
    end;

    5.隐式游标

           显式游标主要是用于对查询语句的处理,尤其是在查询结果为多条记录的情况下;而对于非查询语句,如修改、删除操作,则由ORACLE系统自动地为这些操作设置游标并创建其工作区,这些由系统隐含创建的游标称为隐式游标, 隐式游标的名字为 SQL,这是由 ORACLE 系统定义的。对于隐式游标的操作,如定义、打开、取值及关闭操作,都由 ORACLE系统自动地完成,无需用户进行处理。用户只能通过隐式游标的相关属性,来完成相应的操作。在隐式游标的工作区中,所存放的数据是与用户自定义的显示游标无关的、最新处理的一条SQL语句所包含的数据。

    调用格式为: SQL%

    --更新指定员工 salary(涨工资 10),如果该员工没有找到,则打印”查无此人”信息
    
    begin
             update employees set salary = salary + 10 where employee_id = 1005;
             
             if sql%notfound then
                dbms_output.put_line('查无此人!');
             end if;
    end;



  • 相关阅读:
    centos 下PATH变量配置错误补救办法 Alex
    基于php模块方式安装LAMP和常见LAMP应用 Alex
    php配置 Alex
    php测试小代码 Alex
    PHP简介 Alex
    2.7.JavaScriptnull与undefined
    2.9.JavaScript内置对象
    2.8.JavaScript不同数据类型转换
    2.2.javascript变量作用域
    2.6.Javascript数值型
  • 原文地址:https://www.cnblogs.com/shirui/p/7231015.html
Copyright © 2020-2023  润新知