游标
一、 游标
位于内存中的 "临时表"。 具体如下:游标是从数据表中提取出来的数据,以 临时表 的形式存放到 内存中,在游标中有一个 数据指针, 在初始状态下指向的是首记录,利用 fetch 语句可以移动该指针,从而对游标中的数据进行各种操作,然后将操作结果写回到数据库中。游标的本质是一个结果集resultset,主要用来临时存储从数据库中提取出来的数据块。
二、 游标的分类
1. 显式游标:由用户定义,需要的操作:定义游标、打开游标、提取数据、关闭游标,主要用于对查询语句的处理。
2.显式游标的属性
(1) %NOTFOUND。表示游标获取数据的时候是否有数据提取出来,没有数据返回TRUE,有数据返回false。经常用来判断游标是否全部循环完毕,如案例1%NOTFOUND为true的时候,说明循环完毕,跳出LOOP循环。
(2) %FOUND。正好和%NOTFOUND相反,当游标提取数据值时有值,返回TRUE,否则返回FALSE。
(3) %ISOPEN。用来判断游标是否打开。
(4) %ROWCOUNT。表示当前游标FETCH INTO获取了多少行的记录值,用来做计数用的。
举例:打印表hu_test中的指定字段
--显示游标 declare cursor hu_test_cursor is select owner,object_type,created from hu_test;--定义游标 v_owner hu_test.owner%type; v_object_type hu_test.object_type%type; v_created hu_test.created%type; begin open hu_test_cursor;--打开游标 loop fetch hu_test_cursor into v_owner,v_object_type,v_created;--提取数据 dbms_output.put_line('所有者:'||v_owner||' 类型是:'||v_object_type||' 创建时间:'||v_created); exit when hu_test_cursor%notfound; end loop; close hu_test_cursor;--关闭游标 EXCEPTION WHEN OTHERS THEN dbms_output.put_line(SQLCODE || ' : ' || SQLERRM);--返回错误消息 dbms_output.put_line(dbms_utility.format_error_backtrace);--返回错误行 end;
举例:检验游标是否打开,打开的话显示提取行数
--检验游标是否打开,打开的话显示提取行数
declare
cursor hu_test_cursor is select owner,object_type,created from hu_test;--定义游标
v_owner hu_test.owner%type;
v_object_type hu_test.object_type%type;
v_created hu_test.created%type;
begin
open hu_test_cursor;--打开游标
loop
fetch hu_test_cursor into v_owner,v_object_type,v_created;--提取数据
dbms_output.put_line('所有者:'||v_owner||' 类型是:'||v_object_type||' 创建时间:'||v_created);
exit when hu_test_cursor%notfound;
end loop;
if(hu_test_cursor%isopen) then DBMS_OUTPUT.PUT_LINE('游标已打开');
DBMS_OUTPUT.PUT_LINE('读取了'||hu_test_cursor%ROWCOUNT||'行');
else
DBMS_OUTPUT.PUT_LINE('游标没有打开');
end if;
close hu_test_cursor;--关闭游标
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line(SQLCODE || ' : ' || SQLERRM);--返回错误消息
dbms_output.put_line(dbms_utility.format_error_backtrace);--返回错误行
end;
3. 隐式游标:由系统定义并为它创建工作区域,并且隐式的定义打开提取关闭,隐式游标的游标名就是'SQL',属性和显示游标相同,主要用于对单行select语句或dml操作进行处理。
(1)SQL%ISOPEN:游标是否开启, true:开启,false:关闭
(2)SQL%FOUND:前一个 fetch 语句是否有值,true:有,false:没有
(3)SQL%NOTFOUND:与上述相反,常被用于 退出循环,true:没有,false:有, null : 空。注意哦,只有 为 true 时,才退出(当 第一次 fetch 为 null 时,不会退出!)
(4)SQL%ROWCOUNT:当前成功执行的数据行数(非总记录数)
举例:用隐式游标测试插入,更新,删除,查询等
--隐式游标
declare
v_count number;
begin
insert into hu_test(owner,object_type,created) values('SYS','test',sysdate);
IF SQL%FOUND THEN
dbms_output.put_line('插入成功!');
commit;
END IF;
update hu_test e set e.object_type='CLUSTER1' where e.object_type='CLUSTER';
IF SQL%FOUND THEN
dbms_output.put_line('更新成功!');
commit;
END IF;
delete from hu_test e where e.object_id=3;
IF SQL%FOUND THEN
dbms_output.put_line('删除成功!');
commit;
END IF;
select count(*) into v_count from hu_test;
IF SQL%FOUND THEN
dbms_output.put_line('总记录为: '||v_count);
END IF;
IF SQL%ISOPEN THEN
dbms_output.put_line('可手动查看');
ELSE
dbms_output.put_line('无法手动查看');
END IF;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line(SQLCODE || ' : ' || SQLERRM);
dbms_output.put_line(dbms_utility.format_error_backtrace);
end;
4.游标FOR循环:隐含的执行了打开提取关闭数据,代码精简很多,syntax:
FOR table_record IN table_cursor LOOP STATEMENT; END LOOP;
举例:游标FOR循环
DECLARE
cursor hu_test_cursor is select owner,object_type,created from hu_test;
BEGIN
FOR test_cursor IN hu_test_cursor LOOP
dbms_output.put_line('所有者:'||test_cursor.owner||' 类型是:'||test_cursor.object_type||' 创建时间:'||test_cursor.created);
END LOOP;
END;
这里游标FOR循环省去了对于取到的数据的变量的命名和赋值,同时如果全部打印则不用写循环条件,代码精简了很多。
如果想让代码更加精简,则可以去掉对游标的声明引入子查询即可,操作如下。
--更简便的for循环
BEGIN
FOR test_cursor IN (select owner,object_type,created from hu_test) LOOP
dbms_output.put_line('所有者:'||test_cursor.owner||' 类型是:'||test_cursor.object_type||' 创建时间:'||test_cursor.created);
END LOOP;
END;
5.参数游标,动态游标1
举例:输入object_id查询相关数据
--参数游标
declare
cursor hu_test_cursor(numid number) is select owner,object_type,created from hu_test e where e.object_id=numid;
BEGIN
FOR test_cursor IN hu_test_cursor(&numid) LOOP--这里也可以用一个变量来赋值
dbms_output.put_line('所有者:'||test_cursor.owner||' 类型是:'||test_cursor.object_type||' 创建时间:'||test_cursor.created);
END LOOP;
END;
6.参数游标,动态游标2
--动态游标
declare
v_id hu_test.object_id%type;
v_sql varchar2(2000);
type test_cursor_type is ref cursor;
test_cursor test_cursor_type;
v_owner hu_test.owner%type;
v_object_type hu_test.object_type%type;
v_created hu_test.created%type;
BEGIN
v_id:=20;
v_sql:='select owner,object_type,created from hu_test e where e.object_id = :v_id';
open test_cursor for v_sql using v_id;
loop
fetch test_cursor into v_owner,v_object_type,v_created;
exit when test_cursor%notfound;
dbms_output.put_line('所有者:'||v_owner||' 类型是:'||v_object_type||' 创建时间:'||v_created);
END LOOP;
close test_cursor;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line(SQLCODE || ' : ' || SQLERRM);
dbms_output.put_line(dbms_utility.format_error_backtrace);
END;

浙公网安备 33010602011771号