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