PL/SQL - 嵌套游标 cursor
cursor() 函数可以将一个查询结果集封装成一个类似 REF CURSOR 的游标变量,可以 FETCH 记录,也可以作为 REF CURSOR 类型的参数进行传递。它被称为“嵌套游标(nested cursor)”。*T%d3z!F#w"h,t Z
1. FETCH 记录
4j#T5W,@&Q g0U9{;m"j 我们先看一下测试表 test1 和 test2 的数据:
"x(g;p/Q(o2n'a'l5\TechWeb-技术社区 +K7E9o3r%R:w,}
SQL> select * from test1;
/L-M1}%q!B$| I `'{)O;Z
0E,@4^1P e"D/~0Z$]9^ ATechWeb-技术社区8^7f#v'_.D%G Q;v
----------
%b7t2y5P/@:d'V0c程序开发,操作系统,服务器,源码下载,Linux,Unix,BSD,PHP,Apach,asp,下载,源码,黑客,安全,技术社区,技术论坛 1程序开发,操作系统,服务器,源码下载,Linux,Unix,BSD,PHP,Apach,asp,下载,源码,黑客,安全,技术社区,技术论坛!W2{3p4^"F&C*o
1tech.techweb.com.cn-`"B/x7_:R/_,F#|
2tech.techweb.com.cn6C(}9a;\%{&`
3tech.techweb.com.cn!w)@'?!g/A/m*p
3e2{'v'c$j2pTechWeb-技术社区SQL> select * from test2;
5O6_2F2r1{$k!D *I&I.O)}/H4f
ID NAMETechWeb-技术社区%d6z6V(L/Y$[
---------- ------------------------------------------
4q&v:?-|#?0uTechWeb-技术社区 1 yuechaotian1TechWeb-技术社区+@6g/_0O%V:P%t&{
2 yuechaotian2
-]$D2z(K*E-M4J"c9i6O 3 yuechaotian3$Q6k3O&|3G&m"]5k
4 yuechaotian4TechWeb-技术社区4e:I4e!r.[3J;c9l7H$y+g"V
5 yuechaotian5 TechWeb-技术社区0?*}.q;X8@+a7t/R
/e f#m4k(b)U&i!Y9Z4[
(@$y4I/|7Y7A&d0Q'N3V
我们可能会发出这样一个查询:#R:a%[2a.]"F)V
7Z1a9F7X%F'J.BSQL> select id, name, (select a from test1 where a = test2.id)4E6e.]2l+K;W!H%R
2 from test2;
:z4i0N)e3A)n7u"x'Q-\(qtech.techweb.com.cnselect id, name, (select a from test1 where a = test2.id)
%A;~!{0_8T1U3M9u,dTechWeb-技术社区 *!t$O(a"E:k6j
ERROR 位于第 1 行:6e6I"b1B5{)n.q:W
ORA-01427: 单行子查询返回多个行
.n$y9\6l/l(T.?6?)\程序开发,操作系统,服务器,源码下载,Linux,Unix,BSD,PHP,Apach,asp,下载,源码,黑客,安全,技术社区,技术论坛
"k'S#b&`2| \8k 程序开发,操作系统,服务器,源码下载,Linux,Unix,BSD,PHP,Apach,asp,下载,源码,黑客,安全,技术社区,技术论坛'Q,r0e0z'~#R
因为表 test1 中有两条 a=1 的记录,所以这个查询执行失败了。但有时候我们确实需要这样的查询,怎么办呢?你可以试试 cursor() 函数:TechWeb-技术社区 q%e8P'[#]0r0e8N
程序开发,操作系统,服务器,源码下载,Linux,Unix,BSD,PHP,Apach,asp,下载,源码,黑客,安全,技术社区,技术论坛$J5v4[&s a0R:y
SQL> set serveroutput on
8u2A1j+i!B:fSQL> declare
7a4}3g&w5K4[/K 2 cursor cur_test2 is
,[,c5w5{3Q0h*@7B4k9I程序开发,操作系统,服务器,源码下载,Linux,Unix,BSD,PHP,Apach,asp,下载,源码,黑客,安全,技术社区,技术论坛 3 select id, name, cursor(select a from test1 where a = test2.id)
C*e#@7m1M/m"]+@tech.techweb.com.cn 4 from test2;
*K;c${8X0Q程序开发,操作系统,服务器,源码下载,Linux,Unix,BSD,PHP,Apach,asp,下载,源码,黑客,安全,技术社区,技术论坛 5 rec_test2 test2%rowtype;
8k4Y4^/|9}&M!g:h6d 6
1Q)N+_(k7v7c 7 cur_test1 sys_refcursor;
+W0t;v)r+o8n;i2f/] 8 rec_test1 test1%rowtype;程序开发,操作系统,服务器,源码下载,Linux,Unix,BSD,PHP,Apach,asp,下载,源码,黑客,安全,技术社区,技术论坛:k"M)k6p8x&?
9 begin&S:N c5d)q!O
10 open cur_test2; S+Y5^"_'C'@
11 loop
*@*A$W(H3s"o3b 12 fetch cur_test2 into rec_test2.id, rec_test2.name, cur_test1;
*p)`(^ e J(z)D9e1j%a 13 exit when cur_test2%notfound;
&}.F5M;C2M 14 dbms_output.put_line('rec_test2.id: ' || rec_test2.id || ' | rec_test2.name: ' || rec_test2.name);)e1H O4b;{#p#W0t,T-P
15 -- 这里不需要再显式 OPEN 游标 cur_test1,也不需要显式关闭,f0U3@$];S J6j8v,z;K
16 loopTechWeb-技术社区)S1H5})q(z&Y8H
17 fetch cur_test1 into rec_test1;
/i7L5x+b9c"N;]tech.techweb.com.cn 18 exit when cur_test1%notfound;程序开发,操作系统,服务器,源码下载,Linux,Unix,BSD,PHP,Apach,asp,下载,源码,黑客,安全,技术社区,技术论坛%n;F'\4L2x4G;Q
19 dbms_output.put_line( 'rec_test1.a: ' || rec_test1.a );
&i:t:T,b#h/p,n;p 20 end loop;
1A;Y7[!r!~2i:e f程序开发,操作系统,服务器,源码下载,Linux,Unix,BSD,PHP,Apach,asp,下载,源码,黑客,安全,技术社区,技术论坛 21 end loop;TechWeb-技术社区:]8h,A3L;X(y;V:?'H
22 close cur_test2;2G!W"[,W*_&}
23 end;
1v o*a)`6g;l3y4H4V v 24 /
5s)V r&A+U程序开发,操作系统,服务器,源码下载,Linux,Unix,BSD,PHP,Apach,asp,下载,源码,黑客,安全,技术社区,技术论坛rec_test2.id: 1 | rec_test2.name: yuechaotian1
4E$M0C;C+M!h"I#~:g f1xtech.techweb.com.cnrec_test1.a: 1
2}+W2i2Q4x+{;t#u&}(a }rec_test1.a: 1
1Y7H(O!r9F3h7m3?'T*c程序开发,操作系统,服务器,源码下载,Linux,Unix,BSD,PHP,Apach,asp,下载,源码,黑客,安全,技术社区,技术论坛rec_test2.id: 2 | rec_test2.name: yuechaotian2
)Z4o(N6V!@/]2U d;Wrec_test1.a: 2
%W$_0~&C:c8E;k$y'xrec_test2.id: 3 | rec_test2.name: yuechaotian3
*m:P ~8R&n$e4utech.techweb.com.cnrec_test1.a: 3
6K"D.G3k5Q&G3drec_test2.id: 4 | rec_test2.name: yuechaotian4程序开发,操作系统,服务器,源码下载,Linux,Unix,BSD,PHP,Apach,asp,下载,源码,黑客,安全,技术社区,技术论坛7H9E9h&h7O"h*N.u
rec_test2.id: 5 | rec_test2.name: yuechaotian5
0V:}.v)A&S4_-l;p6Y ,k3q2q6n2E;]0X3W
PL/SQL 过程已成功完成。
|