plsql游标详解——游标中带参数和参数游标不是一回事
2010-05-10 20:26
417 查看
刚打开游标的时候,是位于一个空行,要用fetch into 才能到第一行。
只是要注意用更新游标的时候,不能在游标期间commit. 否则会报
ORA-01002: fetch out of sequence
就是COMMIT;导致错误
在打开有for update的cursor时,系统会给取出的数据加上排他锁(exclusive),
这样在这个锁释放前其他用户不能对这些记录作update、delete和加锁。
而我一旦执行了commit,锁就释放了,游标也变成无效的,再去fetch数据时就出现错误了。
因而要把commit放在循环外,等到所有数据处理完成后再commit,然后关闭cursor
转自:http://hi.baidu.com/tangwei%5Fbd/blog/item/f4adbe02e578391b738b6533.html
只是要注意用更新游标的时候,不能在游标期间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; |
相关文章推荐
- plsql游标详解——游标中带参数和参数游标不是一回事
- PLSQL游标详解
- ASP 游标参数详解(ASP记录集)第1/2页
- PLSql--cursor 显式游标(参数)
- TSQL 带参数的游标 表值类型+record + cursor 模仿 plsql %rowtype
- ASP 游标参数详解(ASP记录集)第1/2页
- Oracle PLSQL Demo - 14.定义定参数的显示游标
- Java中方法调用参数传递的方式是传值,尽管传的是引用的值而不是对象的值。(Does Java pass by reference or pass by value?)
- grep的使用及其参数详解
- Redis配置参数详解
- Linux内核参数详解
- JDK中的URLConnection参数详解
- 61.Scala中隐式参数与隐式转换的联合使用实战详解及其在Spark中的应用源码解析
- PHP中register_globals参数为OFF和ON的区别(register_globals 使用详解)
- jquery的ajax参数详解
- 语音特征参数MFCC提取过程详解
- spring学习之参数传递与检验详解
- x264参数中文详解(X264 Settings)
- kafka broker服务端优化参数详解
- ChannelOption.SO_BACKLOG, 1024-> java socket参数详解:BackLog