oracle游标详解

本文详细介绍了Oracle中的游标,包括隐式游标和显式游标的使用,以及如何进行游标循环。游标作为SQL的一个内存工作区,用于临时存储数据,提高处理速度。文中展示了不同类型的游标操作,如隐式游标的属性,以及如何在循环中使用FETCH、WHILE和FOR循环。此外,还提供了动态SQL和动态游标的概念,强调了在处理多行数据时显式游标的重要性。
摘要由CSDN通过智能技术生成

Oracle游标循环

 
第一种使用loop 循环
          open c_postype;
    0.    loop   
  1.     fetch c_postype into v_postype,v_description ;   
  2.     exit when c_postype%notfound;   
  3.     ……   
  4. end loop  
  5. colse c_postype;

这里需要注意,exit when语句一定要紧跟在fetch之后。必避免多余的数据处理。 
处理逻辑需要跟在exit when之后。这一点需要多加小心。 
循环结束后要记得关闭游标。

 

第二种使用while循环。

            open c_postype;

  1.    fetch c_postype into v_postype,v_description;   
  2.    while c_postype%found loop   
  3.     ……   
  4.        fetch c_postype into v_postype,v_description ;   
  5.      end loop;  
  6. close c_postype;


我们知道了一个游标打开后,必须执行一次fetch语句,游标的属性才会起作用。所以使用while 循环时,就需要在循环之前进行一次fetch动作。 
而且数据处理动作必须放在循环体内的fetch方法之前。循环体内的fetch方法要放在最后。否则就会多处理一次。这一点也要非常的小心。 
总之,使用while来循环处理游标是最复杂的方法。

 

第三种 for循环

          for  v_pos in c_postype loop   
  1.     v_postype := v_pos.pos_type;   
  2.     v_description := v_pos.description;   
  3.     …   
  4. end loop;  

可见for循环是比较简单实用的方法。 
首先,它会自动open和close游标。解决了你忘记打开或关闭游标的烦恼。 
其它,自动定义了一个记录类型及声明该类型的变量,并自动fetch数据到这个变量中。 
我们需要注意v_pos 这个变量无需要在循环外进行声明,无需要为其指定数据类型。 
它应该是一个记录类型,具体的结构是由游标决定的。 
这个变量的作用域仅仅是在循环体内。 
把v_pos看作一个记录变量就可以了,如果要获得某一个值就像调用记录一样就可以了。 
如v_pos.pos_type 
由此可见,for循环是用来循环游标的最好方法。高效,简洁,安全。 
但遗憾的是,常常见到的却是第一种方法。所以从今之后得改变这个习惯了。

 

oracle 隐式游标,显示游标,游标循环,动态SELECT语句和动态游标

游标的概念:
    游标是SQL的一个内存工作区,由系统或用户以变量的形式定义。游标的作用就是用于临时存储从数据库中提取的数据块。在某些情况下,需要把数据从存放在磁盘的表中调到计算机内存中进行处理,最后将处理结果显示出来或最终写回数据库。这样数据处理的速度才会提高,否则频繁的磁盘数据交换会降低效率。
游标有两种类型:显式游标和隐式游标。在前述程序中用到的SELECT...INTO...查询语句,一次只能从数据库中提取一行数据,对于这种形式的查询和DML操作,系统都会使用一个隐式游标。但是如果要提取多行数据,就要由程序员定义一个显式游标,并通过与游标有关的语句进行处理。显式游标对应一个返回结果为多行多列的SELECT语句。
游标一旦打开,数据就从数据库中传送到游标变量中,然后应用程序再从游标变量中分解出需要的数据,并进行处理。 

 

隐式游标 
如前所述,DML操作和单行SELECT语句会使用隐式游标,它们是: 
* 插入操作:INSERT。 
* 更新操作:UPDATE。 
* 删除操作:DELETE。 
* 单行查询操作:SELECT ... INTO ...。 
当系统使用一个隐式游标时,可以通过隐式游标的属性来了解操作的状态和结果,进而控制程序的流程。隐式游标可以使用名字SQL来访问,但要注意,通过SQL游标名总是只能访问前一个DML操作或单行SELECT操作的游标属性。所以通常在刚刚执行完操作之后,立即使用SQL游标名来访问属性。游标的属性有四种,如下所示。

Sql代码  
  1. 隐式游标的属性 返回值类型   意    义   
  2. SQL%ROWCOUNT    整型  代表DML语句成功执行的数据行数   
  3. SQL%FOUND   布尔型 值为TRUE代表插入、删除、更新或单行查询操作成功   
  4. SQL%NOTFOUND    布尔型 与SQL%FOUND属性返回值相反   
  5. SQL%ISOPEN  布尔型 DML执行过程中为真,结束后为假  
【训练1】 使用隐式游标的属性,判断对雇员工资的修改是否成功。  
步骤1:输入和运行以下程序:  
Sql代码  
  1. SET SERVEROUTPUT ON    
  2.         BEGIN  
  3.         UPDATE emp SET sal=sal+100 WHERE empno=1234;   
  4.          IF SQL%FOUND THEN    
  5.         DBMS_OUTPUT.PUT_LINE('成功修改雇员工资!');   
  6.         COMMIT;    
  7.         ELSE  
  8.         DBMS_OUTPUT.PUT_LINE('修改雇员工资失败!');   
  9.          END IF;    
  10.         END;  
运行结果为:  
Sql代码  
  1. 修改雇员工资失败!   
  2.         PL/SQL 过程已成功完成。  
步骤2:将雇员编号1234改为7788,重新执行以上程序:  
运行结果为:  
Sql代码  
  1. 成功修改雇员工资!   
  2.         PL/SQL 过程已成功完成。  
说明:本例中,通过SQL%FOUND属性判断修改是否成功,并给出相应信息。  
显式游标 
游标的定义和操作  
游标的使用分成以下4个步骤。  
1.声明游标  
在DECLEAR部分按以下格式声明游标:  
CURSOR 游标名[(参数1 数据类型[,参数2 数据类型...])]  
IS SELECT语句;  
参数是可选部分,所定义的参数可以出现在SELECT语句的WHERE子句中。如果定义了参数,则必须在打开游标时传递相应的实际参数。  
SELECT语句是对表或视图的查询语句,甚至也可以是联合查询。可以带WHERE条件、ORDER BY或GROUP BY等子句,但不能使用INTO子句。在SELECT语句中可以使用在定义游标之前定义的变量。
2.打开游标  
在可执行部分,按以下格式打开游标:  
OPEN 游标名[(实际参数1[,实际参数2...])];  
打开游标时,SELECT语句的查询结果就被传送到了游标工作区。  
3.提取数据  
在可执行部分,按以下格式将游标工作区中的数据取到变量中。提取操作必须在打开游标之后进行。  
FETCH 游标名 INTO 变量名1[,变量名2...];  
 
FETCH 游标名 INTO 记录变量;  
游标打开后有一个指针指向数据区,FETCH语句一次返回指针所指的一行数据,要返回多行需重复执行,可以使用循环语句来实现。控制循环可以通过判断游标的属性来进行。  
下面对这两种格式进行说明:  
第一种格式中的变量名是用来从游标中接收数据的变量,需要事先定义。变量的个数和类型应与SELECT语句中的字段变量的个数和类型一致。  
第二种格式一次将一行数据取到记录变量中,需要使用%ROWTYPE事先定义记录变量,这种形式使用起来比较方便,不必分别定义和使用多个变量。  
定义记录变量的方法如下:  
变量名 表名|游标名%ROWTYPE;  
其中的表必须存在,游标名也必须先定义。  
4.关闭游标  
CLOSE 游标名;  
显式游标打开后,必须显式地关闭。游标一旦关闭,游标占用的资源就被释放,游标变成无效,必须重新打开才能使用。  
以下是使用显式游标的一个简单练习。  
【训练1】  用游标提取emp表中7788雇员的名称和职务。  
Sql代码  
  1. SET SERVEROUTPUT ON  
  2.         DECLARE    
  3.          v_ename VARCHAR2(10);   
  4.          v_job VARCHAR2(10);   
  5.          CURSOR emp_cursor IS    
  6.          SELECT ename,job FROM emp WHERE empno=7788;   
  7.          BEGIN  
  8.      OPEN emp_cursor;   
  9.     FETCH emp_cursor INTO v_ename,v_job;   
  10.         DBMS_OUTPUT.PUT_LINE(v_ename||','||v_job);   
  11.         CLOSE emp_cursor;   
  12.         END;  
执行结果为:  
Sql代码  
  1. SCOTT,ANALYST   
  2.         PL/SQL 过程已成功完成。   
说明:该程序通过定义游标emp_cursor,提取并显示雇员7788的名称和职务。  
作为对以上例子的改进,在以下训练中采用了记录变量。  
【训练2】  用游标提取emp表中7788雇员的姓名、职务和工资。  
Sql代码  
  1. SET SERVEROUTPUT ON  
  2.         DECLARE  
  3.          CURSOR emp_cursor IS  SELECT ename,job,sal FROM emp WHERE empno=7788;   
  4.          emp_record emp_cursor%ROWTYPE;   
  5.         BEGIN  
  6. OPEN emp_cursor;       
  7.         FETCH emp_cursor INTO emp_record;   
  8.            DBMS_OUTPUT.PUT_LINE(emp_record.ename||','|| emp_record.job||','|| emp_record.sal);   
  9.          CLOSE emp_cursor;   
  10.         END;  
执行结果为:  
Sql代码  
  1. SCOTT,ANALYST,3000   
  2.         PL/SQL 过程已成功完成。   
说明:实例中使用记录变量来接收数据,记录变量由游标变量定义,需要出现在游标定义之后。  
注意:可通过以下形式获得记录变量的内容:  
记录变量名.字段名。  
【训练3】  显示工资最高的前3名雇员的名称和工资。  
Sql代码  
  1. SET SERVEROUTPUT ON  
  2.         DECLARE  
  3.          V_ename VARCHAR2(10);   
  4.         V_sal NUMBER(5);   
  5.         CURSOR emp_cursor IS  SELECT ename,sal FROM emp ORDER BY sal DESC;   
  6.         BEGIN  
  7.          OPEN emp_cursor;   
  8.          FOR I IN 1..3 LOOP   
  9.            FETCH emp_cursor INTO v_ename,v_sal;   
  10.          DBMS_OUTPUT.PUT_LINE(v_ename||','||v_sal);   
  11.           END LOOP;   
  12.          CLOSE emp_cursor;   
  13.          END;  
执行结果为:  
Sql代码  
  1. KING,5000   
  2.      SCOTT,3000   
  3.      FORD,3000   
  4.      PL/SQL 过程已成功完成。  
  说明:该程序在游标定义中使用了ORDER BY子句进行排序,并使用循环语句来提取多行数据
 
游标循环 
【训练1】  使用特殊的FOR循环形式显示全部雇员的编号和名称。  
Sql代码  
  1. SET SERVEROUTPUT ON  
  2. DECLARE  
  3.   CURSOR emp_cursor IS    
  4.   SELECT empno, ename FROM emp;   
  5. BEGIN  
  6. FOR Emp_record IN emp_cursor LOOP      
  7.     DBMS_OUTPUT.PUT_LINE(Emp_record.empno|| Emp_record.ename);   
  8.     
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值