Oracle之游标(显式游标、隐式游标)
1. 游标的定义
在PL/SQL块中执行SELECT、INSERT、DELETE和UPDATE语句时,ORACLE会在内存中为其分配上下文区(Context Area),即缓冲区。游标是指向该区的一个指针,或是命名一个工作区(Work Area),或是一种结构化数据类型。它为应用等量齐观提供了一种对具有多行数据查询结果集中的每一行数据分别进行单独处理的方法,是设计嵌入式SQL语句的应用程序的常用编程方式。
定位行,逐行跳动
2.游标分类
- 显式 游标用于处理SELECT语句返回的多行数据;人为创建,干预
- 隐式 游标用于处理SELECT INTO和非查询的DML语句;系统自动创建,管理
3.常用属性 CURSOR
%ISOPEN
用于确定游标是否已经打开。如果游标已经打开,则返回值为TRUE;否则返回FALSE
%FOUND
检查是否从结果集中提取到数据。如果提取到数据,则返回值为TRUE;否则返回FALSE
%NOTFOUND
与%FOUND属性恰好相反,如果提取到数据,则返回值为FALSE;否则返回TRUE
%ROWCOUNT
返回到当前行为止已经提取到的实际行数
4. 显式游标示例练习
1.显示游标格式
-- 显示游标格式:
-- 1. 定义游标
CURSOR cursor_name IS select_SQL;
-- 2. 打开游标
OPEN cursor_name;
-- 3. 提取数据
FETCH cursor_name INTO variable1,variable2,...;
--当运行fetch后,游标才开始工作,记录当前行,有数据则下移,然后置%FOUND,%NOTFOUND的值
-- 4. 关闭游标
CLOSE cursor_name;
2.显示游标示例
---- 显示游标示例
declare
-- 定义游标,指定SQL集
cursor c_cursor is select * from student;
-- 定义收参变量 rowtype
v_stu student%rowtype;
begin
-- 打开游标
open c_cursor;
-- loop 循环读取游标内容
loop
-- fetch获取游标
fetch c_cursor into v_stu;
exit when c_cursor%notfound;
--打印
dbms_output.put_line(v_stu.id || ' ' || v_stu.name);
end loop;
-- 关闭游标
close c_cursor;
end;
3.游标传参,显示游标
-- 游标传参
declare
--定义一个游标,并指定循环列表
cursor c_cursor(id number) is
select * from student where id=id;
-- 定义收参
v_info student%rowtype;
begin
-- 打开游标,并传入参数
open c_cursor(1);
loop
fetch c_cursor into v_info;
exit when c_cursor%notfound;
dbms_output.put_line(v_info.id);
end loop;
-- 关闭游标
close c_cursor;
end;
5. 隐式游标示例练习
-- 隐式游标 for循环
declare
--定义游标,指定SQL集
cursor c_cursor is select * from student;
-- 隐藏定义收参 rowtype
-- v_stu student%rowtype;
begin
--隐藏打开游标
--open c_cursor();
--loop 循环读取游标内容
for v_stu in c_cursor loop
--打印
dbms_output.put_line(v_stu.id || ' ' || v_stu.name);
end loop;
-- 隐藏关闭游标
-- close c_cursor;
end;
6.隐含游标,当执行一条非查询的DML语句或者SELECT…INTO语句时,都会创建一个隐含游标
- 隐含游标的名称是SQL,不能对SQL游标显式执行OPEN、FETCH和CLOSE语句。
- Oracle隐式地打开、提取,并总是自动地关闭SQL游标
- 隐含游标的属性
SQL%FOUND
SQL%NOTFOUND
SQL%ROWCOUNT
SQL%ISOPEN
示例
declare
v_stuId number := '&input_stuId';
begin
delete from student where stu_id=v_stuId;
if sql%found then
DBMS_OUTPUT.PUT_LINE('找到员工');
else
DBMS_OUTPUT.PUT_LINE('未找到员工');
end if;
end;