为了处理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;
阅读(8149) | 评论(0) | 转发(0) |