前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >PL/SQL学习笔记_02_游标

PL/SQL学习笔记_02_游标

作者头像
shirayner
发布2018-08-10 11:08:54
8290
发布2018-08-10 11:08:54
举报
文章被收录于专栏:Java成神之路

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

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

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

1.处理显示游标

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

(1)定义游标:

代码语言:javascript
复制
CURSOR   cursor_name  [(parameter [, parameter]…) ]   IS   子查询 ;

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

(2)打开游标:

代码语言:javascript
复制
OPEN  cursor_name  [([parameter =>] value [, [parameter =>] value]…)];

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

(3)提取游标数据: 

代码语言:javascript
复制
FETCH  cursor_name  INTO  { variable_list | record_variable };

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

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

(4)关闭游标:  

代码语言:javascript
复制
CLOSE  cursor_name;

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

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

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

示例1:

代码语言:javascript
复制
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:

代码语言:javascript
复制
/*
利用游标, 调整公司中员工的工资: 
    
    工资范围       调整基数
    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;

2.游标属性

%FOUND

布尔型属性,当最近一次读记录时成功返回,则值为 TRUE;

%NOTFOUND

布尔型属性,与%FOUND 相反;

%ISOPEN

布尔型属性,当游标已打开时返回 TRUE;

%ROWCOUNT

数字型属性,返回已从游标中读取的记录数。

3. 游标的 FOR 循环

代码语言:javascript
复制
FOR index_variable  IN  cursor_name[value[, value]…]  LOOP
    -- 游标数据处理代码
END LOOP;

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

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

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

示例1:

代码语言:javascript
复制
/*
 利用游标, 调整公司中员工的工资: 
    
    工资范围       调整基数
    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.带参数的游标

代码语言:javascript
复制
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%

代码语言:javascript
复制
--更新指定员工 salary(涨工资 10),如果该员工没有找到,则打印”查无此人”信息

begin
         update employees set salary = salary + 10 where employee_id = 1005;
         
         if sql%notfound then
            dbms_output.put_line('查无此人!');
         end if;
end;
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017-07-24 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.处理显示游标
    • (1)定义游标:
      • (2)打开游标:
        • (3)提取游标数据: 
          • (4)关闭游标:  
          • 2.游标属性
          • 3. 游标的 FOR 循环
          • 4.带参数的游标
          • 5.隐式游标
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档