游标

来源:互联网 发布:3dmax优化到几核几县 编辑:程序博客网 时间:2024/05/08 23:31

游标的概念: CURSOR cursor_name IS select_statement

      游标是SQL的一个内存工作区,由系统或用户以变量的形式定义。游标的作用就是用于临时存储从数据库中提取的数据块。在某些情况下,需要把数据从存放在磁盘的表中调到计算机内存中进行处理,最后将处理结果显示出来或最终写回数据库。这样数据处理的速度才会提高,否则频繁的磁盘数据交换会降低效率。

显式游标和隐式游标。在前述程序中用到的SELECT...INTO...查询语句,一次只能从数据库中提取一行数据,对于这种形式的查询和DML操作, 系统都会使用一个隐式游标。但是如果要提取多行数据,就要由程序员定义一个显式游标,并通过与游标有关的语句进行处理。显式游标对应一个返回结果为多行多列的SELECT语句。

当系统使用一个隐式游标时,可以通过隐式游标的属性来了解操作的状态和结果,进而控制程序的流程。隐式游标可以使用名字SQL来访问,但要注意,通过 SQL游标名总是只能访问前一个DML操作或单行SELECT操作的游标属性。所以通常在刚刚执行完操作之后,立即使用SQL游标名来访问属性。游标的属性有四种

隐式游标的属性 返回值类型   意义  

  1. SQL%ROWCOUNT   整型      代表DML语句成功执行的数据行数  
  2. SQL%FOUND        布尔型   值为TRUE代表插入、删除、更新或单行查询操作成功
  3. SQL%NOTFOUND   布尔型    与SQL%FOUND属性返回值相反
  4. SQL%ISOPEN       布尔型    DML执行过程中为真,结束后为假

SET SERVEROUTPUT ON   

        BEGIN  

     UPDATE emp SET sal=sal+100 WHERE empno=1234;  

         IF SQL%FOUND THEN   

        DBMS_OUTPUT.PUT_LINE('成功修改雇员工资!');  COMMIT;   

       ELSE  

      DBMS_OUTPUT.PUT_LINE('修改雇员工资失败!');  

         END IF;   

      END;  

     对于查询结果为一行的SELECT语句,可以用动态生成查询语句字符串的方法,在程序执行阶段临时地生成并执行

     语法是:execute immediate 查询语句字符串 into 变量1[,变量2...];

 SET SERVEROUTPUT ON   

        DECLARE   

        str varchar2(100);  

        v_ename varchar2(10);  

        begin  

        str:='select ename from scott.emp where empno=7788';  

        execute immediate str into v_ename;   

        dbms_output.put_line(v_ename);  

 END; 


For循环游标

--(1)定义游标
--(2)定义游标变量
--(3)使用for循环来使用这个游标

1、无参游标

declare
       --类型定义
       cursor c_job
       is
       select empno,ename,job,sal
       from emp
       where job='MANAGER';
       --定义一个游标变量v_cinfo c_emp%ROWTYPE ,该类型为游标c_emp中的一行数据类型
       c_row c_job%rowtype;
begin
       for c_row in c_job loop
         dbms_output.put_line(c_row.empno||'-'||c_row.ename||'-'||c_row.job||'-'||c_row.sal);
       end loop;
end;

2、有参游标

declare 
       --类型定义
       cursor mysor(proname varchar2)
       is
       select * from sys_pro_monitor where pro_name=proname;
       c_row mysor%rowtype;
begin
       for c_row in mysor('PRO_RPT_KPI')  loop
         dbms_output.put_line(c_row.id);
       end loop;
end;

Fetch游标

--使用的时候必须要明确的打开和关闭
declare 
       --类型定义
       cursor c_job
       is
       select empno,ename,job,sal
       from emp
       where job='MANAGER';
       --定义一个游标变量
       c_row c_job%rowtype;
begin
       open c_job;
         loop
           --提取一行数据到c_row
           fetch c_job into c_row;
           --判读是否提取到值,没取到值就退出
           --取到值c_job%notfound 是false 
           --取不到值c_job%notfound 是true
           exit when c_job%notfound;
            dbms_output.put_line(c_row.empno||'-'||c_row.ename||'-'||c_row.job||'-'||c_row.sal);
         end loop;
       --关闭游标
      close c_job;
end;

动态游标的用法

declare        
       TYPE r_fa_vendor IS RECORD(
             l_fcheckid  NUMBER(18),
             l_fdetailid NUMBER(18),
             l_rotleafw  NUMBER(10, 2));
       --(1)声明动态游标
       TYPE myrctype IS REF CURSOR;
       cur_result  r_fa_vendor;
       t_data_cur myrctype;
       --(2)游标对应语句
       querysql VARCHAR2(8000) := 'SELECT a.feed_check_id l_fcheckid, b.feed_detail_id l_fdetailid, a.rotleafweight l_rotleafw FROM cux.cux_inv_feed_check a,
                                                                      cux.cux_inv_feed_detail b where a.feed_check_id = b.feed_check_id ';
    
BEGIN
       --拼接动态sql语句
       IF p_warehouse IS NOT NULL THEN
            querysql := querysql || ' and a.department = ''' || p_warehouse || '''';
       END IF;
       IF p_txt11 IS NOT NULL THEN
            querysql := querysql || ' and trunc(a.senddate)<= to_date( ''' || p_txt11 || ''',''yyyy-MM-dd'')';
       END IF;

       --打开游标,执行循环
       OPEN t_data_cur FOR querysql;
        LOOP
           FETCH t_data_cur
           --把获取到的值,放入记录类型里(记录类型声明的顺序一定要和查询字段顺序一致)
           INTO cur_result;
              EXIT WHEN t_data_cur%NOTFOUND;
              --写入要处理的逻辑
              cur_result.l_fcheckid;
              cur_result.l_fdetailid;
              cur_result.l_rotleafw;
       END LOOP;
       --如果结果只是返回一个值,可以使用
       --execute immediate querysql into v_ename;
       CLOSE t_data_cur;
END;
1 0
原创粉丝点击