Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4006113
  • 博文数量: 536
  • 博客积分: 10470
  • 博客等级: 上将
  • 技术积分: 4825
  • 用 户 组: 普通用户
  • 注册时间: 2006-05-26 14:08
文章分类

全部博文(536)

文章存档

2024年(3)

2021年(1)

2019年(1)

2017年(1)

2016年(2)

2013年(2)

2012年(10)

2011年(43)

2010年(10)

2009年(17)

2008年(121)

2007年(252)

2006年(73)

分类: Oracle

2007-01-31 11:09:42

   为了处理sql语句,Oracle必须分配一片内存区域——上下文区域(context area),它包含了完成该处理所必需的信息, 其中包括语句要处理行的数目、 一个指向语句被分析以后产生的表示形式的指针, 以及查询的活动集(active set 即查询返回的行的集合)。
   游标(cursor)是一个指向上下文区的句柄(handle)或指针。 通过游标, pl/sql程序可以控制上下文区和处理语句时上下文区发生什么
事情。  

静态游标, 显式游标和隐式游标  

显式游标的处理包括四个pl/sql步骤,如下:  
    1)声明游标。  
    2)为查询打开游标。  
    3)将结果提取(fetch)到pl/sql变量中。  
    4)关闭游标。  

游标声明  
对游标的声明定义了游标的名字并将该游标和一个SELECT语句相关联。
语法是:
    CURSOR cursor_name IS SELECT_statement;  
   任何的SELECT 语句都是合法的,包括连接(join)和带有UNION或MINUS子句的语句,但是不能包含INTO子句,游标的声明可以在WHERE子句中引用pl/sql变量。这些变量被认为是联编变量(bind variable,即已经被分配空间并映射到绝对地址的变量)  

游标打开  
当打开一个游标时会发生下面的事情:  
    a.联编变量的取值被检查。  
    b.根据联编变量的取值,活动集被确定。  
    c.活动集的指针指向第一行。  
在游标打开时刻并且仅仅在游标打开时刻对联编变量进行检查。  

游标的属性  
在pl/sql中可以使用游标的四个属性。pl/sql块中,游标属性附加在游标名的后边。游标属性返回的不是类型(如%type,%rowtype),它返回的是在表达式中可以使用的数值。这些属性是%FOUND、%NOTFOUND、%ISOPEN、%ROWCOUNT。  
    a.%FOUND是一个布尔属性。如果前一个FETCH语句返一个行,那么它的返回TRUE, 否则FALSE。如果在未打开游标以前就设置了%FOUND,那么回返回ora-1001(无效得游标)。  
    b.%NOTFOUND的行为方式与%FOUND正好相反。  
    c.%ISOPEN也是布尔属性,用来确定相关的游标是否被打开了。  
    d.%ROWCOUNT此数字属性返回目前为止由游标返回行的数目。如果在相关联的游标还没有打开或者已经关闭的时候进行引用,那么
也会返回ora-1001错误。  

处理隐式游标  
显式游标用来处理返回多于一行的SELECT语句,但是所有的SQL语句在上下文区内部是可执行的,因此都有一个游标指向此上下文区。此游标就是所谓的“SQL 游标”(SQL cursor)。 与显式游标不同的是, SQL游标不被程序打开和关闭。 pl/sql隐含地打开SQL游标,处理其中的SQL语句,然后关闭该游标。  
   隐式游标用于处理INSERT、UPDATE、DELETE和单行的SELECT..INTO语句。因为SQL 游标是通过pl/sql 引擎打开和关闭的,所以OPEN、FETCH、CLOSE命令是无关的。但是游标属性(用SQL%..)可以被应用于SQL游标。

Ref:

eg:
CREATE OR REPLACE PROCEDURE OSM_DML_2SP.OSM_TAB_PROCPROC2(
    ival IN OSM_TAB_PROC.COL_0%TYPE:=10,
    ocnt IN OUT NUMBER)
AS
  a OSM_TAB_PROC.COL_0%TYPE;
  r OSM_TAB_PROC%ROWTYPE;
  i NUMBER := 0;
  CURSOR c1(ct0 NUMBER) IS SELECT COL_0 FROM OSM_DML_2SP.OSM_TAB_PROC WHERE COL_0>ct0;
BEGIN
  IF c1%ISOPEN = FALSE THEN
    OPEN c1(60);
  END IF;

  LOOP
    EXIT WHEN c1%NOTFOUND; -- if cursor is not open used it ORA-01001 error
    FETCH c1 INTO a;

    SELECT * INTO r FROM OSM_DML_2SP.OSM_TAB_PROC WHERE COL_0=a AND ROWNUM<2;
    r.COL_0 := a + ival;
    r.COL_3 := TO_CHAR(a) || TO_CHAR(SYSDATE);
    INSERT INTO OSM_DML_2SP.OSM_TAB_PROC VALUES r;
    i := i + 1;
  END LOOP;

  CLOSE c1;
  ocnt := i;
END;

DECLARE
  cnt NUMBER := 0;
BEGIN
  FOR i IN 1 .. 3 LOOP
    OSM_DML_2SP.OSM_TAB_PROCPROC2(236*i,cnt);

    EXECUTE IMMEDIATE 'INSERT INTO OSM_DML_2SP.OSM_TAB_PROC(COL_0) VALUES(:1)' USING cnt*i;
  END LOOP;
END;
阅读(8106) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~