游标有两种类型:显示游标和隐式游标
隐式游标的属性 返回值类型 意见
SQL%ROWCOUNT 整型 代表DML语句成功执行的数据行数
SQL%FOUND 布尔型 值为TRUE代表插入、删除、更新或单行查询操作成功
SQL%NOTFOUND 布尔型 与SQL%FOUND返回值相反
SQL%ISOPEN 布尔型 DML执行过程中为真,结束后为假
-- 使用隐式游标执行更新操作
begin
update emp set sal = 1000 where deptno = 10;
if SQL%FOUND THEN
dbms_output.put_line('update success');
commit;
else
dbms_output.put_line('update false');
end if;
end;
游标的定义和操作
--声明游标
declare
变量1 数据类型1;
变量2 数据类型2;
cursor 游标名称(参数1 数据类型1, 参数2 数据类型2,... )
IS SELECT语句;
--打开游标
OPEN 游标名称(参数1 数据类型1, 参数2 数据类型2,... )
--提取数据
FETCH 游标名称 INTO 变量1,变量2;
或者
FETCH 游标名称 INFO 记录变量;
--关闭游标
close 游标名称
--用游标获取deptno=10的名称和sal
declare
v_ename varchar2(30);
v_sal varchar2(30);
cursor emp_cursor is
select ename,sal from emp where deptno = 10;
begin
open emp_cursor;
FETCH emp_cursor INTO v_ename,v_sal;
DBMS_OUTPUT.put_line(v_ename||' '||v_sal);
close emp_cursor;
end;
OR
declare
cursor emp_cursor is
select ename,sal from emp where deptno = 10;
emp_record emp_cursor%ROWTYPE;
begin
open emp_cursor;
FETCH emp_cursor INTO emp_record;
Dbms_Output.put_line(emp_record.ename||' '||emp_record.sal);
close emp_cursor;
end;
--用游标获取deptno=10的前3条数据
declare
v_ename varchar2(30);
v_sal varchar2(30);
cursor emp_cursor is
select ename,sal from emp where deptno = 10;
begin
open emp_cursor;
FOR I IN 1..3 LOOP
FETCH emp_cursor INTO v_ename,v_sal;
DBMS_OUTPUT.put_line(v_ename||' '||v_sal);
END LOOP;
close emp_cursor;
end;
--用游标获取deptno=10的所有数据,隐含了记录变量的定义、游标的打开、提取和关闭过程
declare
cursor emp_cursor is
select ename,sal from emp where deptno = 10;
begin
for emp_record IN emp_cursor LOOP
Dbms_Output.put_line(emp_record.ename||' '||emp_record.sal||' '||emp_cursor%ROWCOUNT);
END LOOP;
end;
--还有一种更简单的方法
begin
for emp in (select ename,sal from emp where deptno = 10) LOOP
Dbms_Output.put_line(emp.ename||' '||emp.sal);
end loop;
end;
--用游标获取表中数据,循环的使用,需要退出条件
declare
v_ename varchar2(30);
v_sal varchar2(30);
cursor emp_cursor is
select ename,sal from emp;
begin
open emp_cursor;
LOOP
FETCH emp_cursor INTO v_ename,v_sal;
EXIT WHEN emp_cursor%NOTFOUND; --当FETCH没有成功执行,退出循环
DBMS_OUTPUT.put_line('123:'||v_ename||' '||v_sal);
END LOOP;
close emp_cursor;
end;
--带参数的游标
declare
v_ename varchar2(30);
v_sal varchar2(30);
cursor emp_cursor(p_deptno varchar2,p_sal varchar2) is
select ename,sal from emp where deptno = p_deptno and sal = p_sal;
emp_record emp_cursor%ROWTYPE;
begin
open emp_cursor('20','8000');
LOOP
FETCH emp_cursor INTO v_ename,v_sal;
EXIT WHEN emp_cursor%NOTFOUND;
DBMS_OUTPUT.put_line(v_ename||v_sal);
END LOOP;
close emp_cursor;
end;
OR
declare
v_name varchar2(30);
v_sal varchar2(30);
v_deptno varchar2(20);
cursor emp_cursor is
select ename,sal from emp where deptno = v_deptno and sal = v_sal;
begin
v_deptno:='20';
v_sal:='6000';
open emp_cursor;
LOOP
FETCH emp_cursor INTO v_name,v_sal;
EXIT WHEN emp_cursor%NOTFOUND;
DBMS_OUTPUT.put_line(v_name||v_sal);
END LOOP;
END;
--有异常处理的游标,位于可执行部分之后,由WHEN语句引导的多个分支
declare
v_ename varchar2(30);
v_sal varchar2(30);
cursor emp_cursor(p_deptno varchar2,p_sal varchar2) is
select ename,sal from emp where deptno = p_deptno and sal = p_sal;
emp_record emp_cursor%ROWTYPE;
begin
open emp_cursor('20','8000');
LOOP
FETCH emp_cursor INTO v_ename,v_sal;
EXIT WHEN emp_cursor%NOTFOUND;
DBMS_OUTPUT.put_line(v_ename||v_sal);
END LOOP;
close emp_cursor;
EXCEPTION
WHEN INVALID_CURSOR THEN
DBMS_OUTPUT.put_line('试图使用没有打开的游标');
end;