游标是oracle中的一个结果集,用于存放查询的结果;
PL/SQL中游标的声明;
1,声明游标
2,打开游标(默认是关闭的);
3,提取数据
4,关闭游标
注意的要点:游标必须声明在declare中,使用open打开游标,fetch取游标中的数据,close关闭游标
隐式游标:主要是对DML数据的操作隐式游标的属性有:隐式游标不能使用select into
%FOUND – SQL 语句影响了一行或多行时为 TRUE
%NOTFOUND – SQL 语句没有影响任何行时为TRUE
%ROWCOUNT – SQL 语句影响的行数
%ISOPEN - 游标是否打开,始终为FALSE
显示游标
PL/SQL包含隐含游标和显示游标两种游标类型,其中隐含游标用于处理SELECT INTO和DML语句。而显示游标则专门用于SELECT语句返回的多行数据。
-----------------------------隐式游标类型
--隐式游标 使用DML语句时自动创建隐式游标
--DML 添加 删除,修改数据的时候(会涉及到数据的变化)
%found 发现数据,%notfound没有发现数据,%isopen游标是否打开,%rowCount受影响的行数
例子;在更新数据中使用游标测试隐式游标
在操作DML数据的时候默认有一个隐式游标sql
declare--声明pl/sql块
begin
update emp set sal=3000 where ename='SMITH';--更新语句
if sql%found then --如果发现语句
dbms_output.put_line('有'||sql%rowcount||'行受到影响');
else --否则
dbms_output.put_line('没有数据更新');
end if;
if sql%isopen then --如果游标打开,游标默认是关闭的
dbms_output.put_line('游标被打开');
else --游标没有打开
dbms_output.put_line('游标没有被打开');
end if;
end;
/
结果;
有1行受到影响
游标没有被打开
-----------------------------显示游标
显示游标用来存放数据的,这也是游标主要功能
%rowtype和%type相似,%rowtype存放的是全部字段,%type只能匹配一个字段,--使用%rowtype 存放查询语句返回的一条数据,
%typehe %rowtype的区别;
声明emp表的全部字段
--%type声明emp表中的全部字段
declare
type emp_type_record is record(
v_ename emp.ename%type;
v_sal emp.sal%type;
v_empno emp.empno%type;
..........
);
begin
end
%rowtype声明emp表的全部字段
declare
v_rowtype emp%rowtype;
begin
end;
使用%rowtype来打印emp表部门10的数据
declare
myrow emp%rowtype;
begin
select ename,job,sal into myrow.ename,myrow.job,myrow.sal from emp where empno=10;
dbms_output.put_line('ename:'||myrow.ename);
end;
ORA-01403: 未找到任何数据
ORA-06512: 在 line 5
-------------------显示静态游标
要接受多行数据必须使用游标来接受;
declare
myrow emp%rowtype;
cursor rowcursor is select * from emp where deptno=&a;--声明游标
begin
--使用循环来取数据
for myrow in rowcursor loop
dbms_output.put_line(myrow.ename||'+++++++++++'||myrow.sal);
end loop;
end;
CLARK+++++++++++2450
KING+++++++++++5000
MILLER+++++++++++1300
游标带参数的类型
declare
myrow emp%rowtype;
cursor rowcursor(v_deptno number) is select * from emp where deptno=v_deptno;--声明游标
begin
--使用循环来取数据
for myrow in rowcursor(10) loop
dbms_output.put_line(myrow.ename||'+++++++++++'||myrow.sal);
end loop;
end;
CLARK+++++++++++2450
KING+++++++++++5000
MILLER+++++++++++1300
fetch来取游标的数据 for循环和fetch来取游标需要特别的注意;
declare
myrow emp%rowtype;
cursor rowcorsor is select * from emp where deptno=&a;
begin
--打开游标
open rowcorsor;
loop
fetch rowcorsor into myrow;
exit when rowcorsor%notfound;
dbms_output.put_line(myrow.ename||'+++++++'||myrow.sal);
end loop;
end;
/
CLARK+++++++2450
KING+++++++5000
MILLER+++++++1300
--------------------------游标的更新
查询部门20的姓名等字段,更新SMITH的工资
declare
myrow emp%rowtype;
cursor rowcursor(v_deptno number) is select * from emp where deptno=v_deptno;--声明游标
begin
--使用循环来取数据
for myrow in rowcursor(20) loop
dbms_output.put_line('更新前:'||myrow.ename||'+++++++++++'||myrow.sal);
end loop;
update emp set sal=3000 where ename='SMITH';
for myrow in rowcursor(20) loop
dbms_output.put_line('更新后:'||myrow.ename||'+++++++++++'||myrow.sal);
end loop;
end;
更新前:SMITH+++++++++++1000
更新前:JONES+++++++++++2975
更新前:SCOTT+++++++++++3000
更新前:ADAMS+++++++++++1100
更新前:FORD+++++++++++3000
更新后:SMITH+++++++++++3000
更新后:JONES+++++++++++2975
更新后:SCOTT+++++++++++3000
更新后:ADAMS+++++++++++1100
更新后:FORD+++++++++++3000
----------------------------游标的删除
删除游标中部门20 的SMITH;为了测试,设置一个保存点a savepoint a; 方便回复 rollback to a;
declare
myrow emp%rowtype;
cursor rowcursor(v_deptno number) is select * from emp where deptno=v_deptno;--声明游标
begin
--使用循环来取数据
for myrow in rowcursor(20) loop
dbms_output.put_line('更新前:'||myrow.ename||'+++++++++++'||myrow.sal);
end loop;
delete emp where ename='SMITH';
for myrow in rowcursor(20) loop
dbms_output.put_line('更新后:'||myrow.ename||'+++++++++++'||myrow.sal);
end loop;
end;
更新前:JONES+++++++++++2975
更新前:SCOTT+++++++++++3000
更新前:ADAMS+++++++++++1100
更新前:FORD+++++++++++3000
更新后:JONES+++++++++++2975
更新后:SCOTT+++++++++++3000
更新后:ADAMS+++++++++++1100
更新后:FORD+++++++++++3000
---------------------------显示动态游标 ref cursor
declare
type emp_type_cursor is ref cursor;
mycursor emp_type_cursor;
v_row emp%rowtype;
begin
open mycursor for select * from emp where deptno=&a;
loop
fetch mycursor into v_row;
exit when mycursor%notfound;
dbms_output.put_line(v_row.ename);
end loop;
end;
SMITH
JONES
SCOTT
ADAMS
FORD