刚打开游标的时候,是位于一个空行,要用fetch into 才能到第一行。
只是要注意用更新游标的时候,不能在游标期间commit. 否则会报
ORA-01002: fetch out of sequence
就是COMMIT;导致错误
在打开有for update的cursor时,系统会给取出的数据加上排他锁(exclusive),
这样在这个锁释放前其他用户不能对这些记录作update、delete和加锁。
而我一旦执行了commit,锁就释放了,游标也变成无效的,再去fetch数据时就出现错误了。
因而要把commit放在循环外,等到所有数据处理完成后再commit,然后关闭cursor
隐含游标
--------
又名SQL游标,用于处理单行select into 和 DML语句。
SQL%ISOPEN SQL%FOUND SQL%NOTFOUND SQL%ROWCOUNT
显示游标
--------
用户处理select语句返回的多行数据。
select语句返回多行数据处理方式:[1]显示游标;[2]select ... bulk collect into 集合变量...;
【1】显示游标属性
[1] %ISOPEN 检测游标是否打开。
[2] %FOUND 检测游标结果集是否存在数据。
[3] %NOTFOUND 是否不存在数据。
[4] %ROWCOUNT 游标已提取的实际行数。
【2】使用显示游标
[1] 定义游标
CURSOR cursor_name IS select_statement;
[2] 打开游标
OPEN cursor_name;
[3] 提取数据
FECTH cursor_name INTO variable,...;
[4] 关闭数据
CLOSE cursor_name;
使用标量变量:
-------------
DECLARE
Cursor emp_cur IS select ename,sal from emp order by empno;
v_ename emp.ename%TYPE;
v_sal emp.sal%TYPE;
BEGIN
IF NOT emp_cur%ISOPEN THEN
OPEN emp_cur;
DBMS_OUTPUT.PUT_LINE('打开游标');
END IF;
NULL;
LOOP
FETCH emp_cur INTO v_ename,v_sal;
EXIT WHEN emp_cur%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('用户名:'||v_ename||',工资:'||v_sal);
END LOOP;
NULL;
IF emp_cur%ISOPEN THEN
CLOSE emp_cur;
DBMS_OUTPUT.PUT_LINE('关闭游标');
END IF;
END;
使用PLSQL记录变量
-----------------
DECLARE
Cursor emp_cur IS select ename,sal from emp order by empno;
emp_record emp_cur%ROWTYPE;
BEGIN
IF NOT emp_cur%ISOPEN THEN
OPEN emp_cur;
DBMS_OUTPUT.PUT_LINE('打开游标');
END IF;
NULL;
LOOP
FETCH emp_cur INTO emp_record;
EXIT WHEN emp_cur%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('用户名:'||emp_record.ename||',工资:'||emp_record.sal);
END LOOP;
NULL;
IF emp_cur%ISOPEN THEN
CLOSE emp_cur;
DBMS_OUTPUT.PUT_LINE('关闭游标');
END IF;
END;
使用PLSQL集合变量
-----------------
DECLARE
Cursor emp_cur IS select ename,sal from emp order by empno;
TYPE emp_table_type IS TABLE OF emp_cur%ROWTYPE INDEX BY BINARY_INTEGER;
emp_table emp_table_type;
i number;
BEGIN
i := 1;
IF NOT emp_cur%ISOPEN THEN
OPEN emp_cur;
DBMS_OUTPUT.PUT_LINE('打开游标');
END IF;
NULL;
LOOP
FETCH emp_cur INTO emp_table(i);
EXIT WHEN emp_cur%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('用户名:'||emp_table(i).ename||',工资:'||emp_table(i).sal);
i := i + 1;
END LOOP;
NULL;
IF emp_cur%ISOPEN THEN
CLOSE emp_cur;
DBMS_OUTPUT.PUT_LINE('关闭游标');
END IF;
END;
【3】循环游标
FOR record_name IN cursor_name|select_statement LOOP
statement;
....
END LOOP;
使用循环游标
------------
declare
cursor emp_cusor is select ename,sal from emp where deptno = &no order by empno;
begin
for emp_record in emp_cusor loop
dbms_output.put_line('姓名:'||emp_record.ename||',工资:'||emp_record.sal);
end loop;
end;
begin
for emp_record in (select ename,sal from scott.emp where deptno = &no order by empno) loop
dbms_output.put_line('姓名:'||emp_record.ename||',工资:'||emp_record.sal);
end loop;
end;
【4】参数游标
CURSOR cursor_name(parameter_name datatype) IS select_statement; --只能制定类型,不能指定具体大小
OPEN cursor_name(参数值);
FECTH cursor_name INTO variable,...;
CLOSE cursor_name;
使用游标参数
------------
示例1:
------
declare
cursor emp_cursor(v_depnto number) is select ename,sal from scott.emp where deptno = v_depnto order by empno;
emp_record emp_cursor%rowtype;
v_dno number;
begin
v_dno := &no;
if not emp_cursor%isopen then
open emp_cursor(v_dno);
end if;
null;
loop
fetch emp_cursor into emp_record;
exit when emp_cursor%notfound;
dbms_output.put_line('姓名:'||emp_record.ename||',工资:'||emp_record.sal);
end loop;
null;
if emp_cursor%isopen then
close emp_cursor;
end if;
end;
示例2
-----
declare
cursor emp_cursor(v_depnto number) is select ename,sal from scott.emp where deptno = v_depnto order by empno;
v_dno number;
begin
v_dno := &no;
for emp_record in emp_cursor(v_dno) loop
dbms_output.put_line('姓名:'||emp_record.ename||',工资:'||emp_record.sal);
end loop;
end;
【5】更新、删除游标行
CURSOR cursor_name IS select_statement
FOR UPDATE [OF column_reference] [NOWAITE]; -- OF子句指定对特定表加锁。
UPDATE table_name SET column=.. WHERE CURRENT OF cursor_name;
DELETE table_name WHERE CURRENT OF cursor_name;
使用游标更新数据
----------------
declare
cursor test_cursor is select empno,ename,sal,deptno from scott.test for update;
test_record test_cursor%rowtype;
v_deptno number;
v_sal test.sal%type;
begin
v_deptno := &no;
if not test_cursor%isopen then
open test_cursor;
end if;
loop
fetch test_cursor into test_record;
exit when test_cursor%notfound;
dbms_output.put_line('姓名:'||test_record.ename||',旧工资:'||test_record.sal);
if test_record.deptno = v_deptno then
update scott.test set sal=2*sal where current of test_cursor;
else
update scott.test set sal=3*sal where current of test_cursor;
end if;
end loop;
close test_cursor;
end;
declare
cursor test_cursor is select empno,ename,sal,deptno from scott.test for update;
v_deptno NUMBER:=&dno;
begin
for test_record in test_cursor loop
if test_record.deptno = v_deptno then
dbms_output.put_line('姓名:'||test_record.ename||',旧工资:'||test_record.sal);
update scott.test set sal = sal*1.5 where current of test_cursor;
end if;
end loop;
end;
表test换成emp出现ORA-01410: 无效的 ROWID错误,什么原因???
使用游标删除数据
----------------
declare
cursor test_cursor(v_deptno number) is select deptno,empno,ename,comm from scott.test where deptno = v_deptno for update;
v_dno test.deptno%type := &dno;
begin
for test_record in test_cursor(v_dno) loop
if test_record.comm is null then
dbms_output.put_line('用户名:'||test_record.ename||'部门:'||test_record.deptno);
delete from scott.test where current of test_cursor;
end if;
end loop;
end;
【6】游标变量
指向内存地址的指针。可以在打开游标时指定其所对应的SELECT语句,实现动态游标。
[1]定义REF CURSOR类型和游标变量:
Type ref_type_name IS REF CURSOR [RETURN return_type --必须是PL/SQL记录类型];
说明:如果指定RETURN子句,那么在打开游标时SELECT语句的返回结果必须与RETURN子句所指定的记录类型匹配。
cursor_variable ref_type name;
SYS_REFCURSOR
[2]打开游标,指定对应的SELECT语句:
OPEN cursor_variable FOR select_statement;
[3]提取数据
FETCH cursor_variable INTO variable1,variable,...;
[4]关闭游标
CLOSE cursor_variable;
不使用RETURN子句
----------------
DECLARE
TYPE ref_type_table IS REF CURSOR;
v_cursor ref_type_table;
emp_record emp%rowtype;
BEGIN
OPEN v_cursor FOR select * from emp where deptno=&no;
LOOP
FETCH v_cursor INTO emp_record;
EXIT WHEN v_cursor%NOTFOUND;
dbms_output.put_line('员工号:'||emp_record.ename||'部门号:'||emp_record.deptno);
END LOOP;
CLOSE v_cursor;
END;
使用RETURN子句
--------------
DECLARE
emp_record emp%rowtype;
TYPE ref_type_table IS REF CURSOR RETURN emp%rowtype;
v_cursor ref_type_table;
BEGIN
OPEN v_cursor FOR select * from emp where deptno=&no;
LOOP
FETCH v_cursor INTO emp_record;
EXIT WHEN v_cursor%NOTFOUND;
dbms_output.put_line('员工号:'||emp_record.ename||'部门号:'||emp_record.deptno);
END LOOP;
CLOSE v_cursor;
END;
DECLARE
Type emp_record_type IS RECORD(
ename emp.ename%TYPE,
salary emp.sal%TYPE,
deptno emp.deptno%TYPE);
emp_record emp_record_type;
TYPE ref_type_table IS REF CURSOR RETURN emp_record_type;
v_cursor ref_type_table;
BEGIN
OPEN v_cursor FOR select ename,sal,deptno from emp where deptno=&no;
LOOP
FETCH v_cursor INTO emp_record;
EXIT WHEN v_cursor%NOTFOUND;
dbms_output.put_line('员工号:'||emp_record.ename||',部门号:'||emp_record.deptno||',工资:'||emp_record.salary);
END LOOP;
CLOSE v_cursor;
END;
【7】使用游标批量获取
FETCH ... BULK COLLECT INTO ...[LIMIT row_number];
不限制行数
----------
DECLARE
CURSOR emp_cursor(v_deptno number) IS SELECT * FROM EMP WHERE deptno = v_deptno;
TYPE type_emp_table IS TABLE OF emp%ROWTYPE INDEX BY BINARY_INTEGER;
emp_table type_emp_table;
v_dno emp.deptno%TYPE;
BEGIN
v_dno := &no;
OPEN emp_cursor(v_dno);
FETCH emp_cursor BULK COLLECT INTO emp_table;
CLOSE emp_cursor;
FOR i IN 1..emp_table.COUNT LOOP
dbms_output.put_line('员工号:'||emp_table(i).ename||'工资:'||emp_table(i).sal);
END LOOP;
CLOSE emp_cursor;
END;
限制行数
--------
DECLARE
CURSOR emp_cursor(v_deptno number) IS SELECT * FROM EMP WHERE deptno = v_deptno;
TYPE type_emp_table IS TABLE OF emp%ROWTYPE INDEX BY BINARY_INTEGER;
emp_table type_emp_table;
v_dno emp.deptno%TYPE;
BEGIN
v_dno := &no;
OPEN emp_cursor(v_dno);
FETCH emp_cursor BULK COLLECT INTO emp_table LIMIT &2;
CLOSE emp_cursor;
FOR i IN 1..emp_table.COUNT LOOP
dbms_output.put_line('员工号:'||emp_table(i).ename||'工资:'||emp_table(i).sal);
END LOOP;
CLOSE emp_cursor;
END;
【8】使用CURSOR表达式
作用嵌套游标。
DECLARE
CURSOR dept_emp_cursor(v_deptno number) IS
SELECT dname,cursor(SELECT * FROM emp e WHERE e.deptno = d.deptno)
FROM dept d WHERE deptno = v_deptno;
TYPE emp_cursor_type IS REF CURSOR;
emp_cursor emp_cursor_type;
emp_record emp%ROWTYPE;
v_name dept.dname%TYPE;
v_dno emp.deptno%TYPE;
BEGIN
v_dno := &no;
OPEN dept_emp_cursor(v_dno);
loop
FETCH dept_emp_cursor INTO v_name,emp_cursor;
EXIT WHEN dept_emp_cursor%NOTFOUND;
dbms_output.put_line('部门名称:'||v_name);
LOOP
FETCH emp_cursor INTO emp_record;
EXIT WHEN emp_cursor%NOTFOUND;
dbms_output.put_line('员工名称:'||emp_record.ename||',工资:'||emp_record.sal);
END LOOP;
end loop;
CLOSE dept_emp_cursor;
END;
转自:http://hi.baidu.com/tangwei%5Fbd/blog/item/f4adbe02e578391b738b6533.html
分享到:
相关推荐
Oracle中PLSQL游标简介
Oracle PLSQL游标的学习! 值得下载看看!资源免费,大家分享!!
Oracle_PLSQL游标的学习资料 详细讲解Oracle_PLSQL游标使用
oracle数据库里plsql游标、集合及对象的简单使用,适合初学者查看
游标提供了一种对从表中检索出的数据进行操作的灵活手段,就本质而言,游标实际上是一种能从包括多条数据记录的结果集中每次提取一条记录的机制。
相信讲述了游标以及它的一些应用实例,在while,if 和for循环下的代码编写。
plsql 显性游标 游标字面理解就是游动的光标。 用数据库语言来描述:游标是映射在结果集中一行数据上的位置实体,有了游标,用户就可以访问结果集中的任意一行数据了,将游标放置到某行后,即可对该行数据进行操作...
用PLSQL进行游标编程,其中包括PPT资料,以及相关实例。
Oracle数据库实验-PLSQL游标、过程、函数、包的使用[文].pdf
PLSQL 存储过程 语法
声明:本文中的所有代码均是实战敲出来的!杜绝copy! 代码是以游标的编写、调用、为目的。从简单到复杂,用迭代的思想不断丰富例子功能。希望对各位同学有所帮助。
福建省电力公司oracle培训教材--PLSQL之游标与异常处理
plsql编程关于游标的使用方法
本例简单介绍一下游标处理的4个过程中涉及到的加锁,一致性读的问题. 显式游标处理需四个 PLSQL步骤: 1、定义/声明游标:是定义一个游标名,以及与其相对应的SELECT 语句。 格式: CURSOR cursor_...
Oracle PLSQL语言初级教程之游标
OraclePL/SQL练习,基本的OraclePL/SQL的语法,游标的在PL/SQL中的使用,如何声明游标,打开游标,提取记录,关闭游标。
详细介绍oracle plsql 的相关概念,包括plsql的组成元素,流控制语句,游标,存储过程和函数,包,异常处理
本文对ORA-01000_maximum_open_cursors_exceeded_超出打开游标的最大数的原因和解决方案有详细描述
如题,初步研究了pl/sql的写法,现给出存储过程,游标等的使用,后续会给出其他的用法
语法入门、操作plsql、存储过程、函数、触发器、游标、包、返回类型;一个execle表轻松搞定。