a我考网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 198|回复: 2

[综合] Oracle辅导:浅谈关于ORACLE中的游标Cursor总结(2)

[复制链接]
发表于 2012-8-4 13:54:49 | 显示全部楼层 |阅读模式
1.4 游标的更新和删除   在PL/SQL中依然可以使用UPDATE和DELETE语句更新或删除数据行。显式游标只有在需要获得多行数据的情况下使用。PL/SQL提供了仅仅使用游标就可以执行删除或更新记录的方法。
2 h/ z9 o5 w+ @6 y  ]7 g- v) E! }  UPDATE或DELETE语句中的WHERE CURRENT OF子串专门处理要执行UPDATE或DELETE操作的表中取出的最近的数据。要使用这个方法,在声明游标时必须使用FOR UPDATE子串,当对话使用FOR UPDATE子串打开一个游标时,所有返回集中的数据行都将处于行级(ROW-LEVEL)独占式锁定,其他对象只能查询这些数据行,不能进行 UPDATE、DELETE或SELECT...FOR UPDATE操作。' O( e; A4 Y) u/ {
  在多表查询中,使用OF子句来锁定特定的表,如果忽略了OF子句,那么所有表中选择的数据行都将被锁定。如果这些数据行已经被其他会话锁定,那么正常情况下ORACLE将等待,直到数据行解锁。+ Q. ?& h4 [" b! j) {- b! i
  在UPDATE和DELETE中使用WHERE CURRENT OF子串的语法如下:
! X  c, ?+ k3 U3 |6 b( d1 O9 V  WHERE{CURRENT OF cursor_name|search_condition}
% p- P+ _# o" h, E- o  例:
8 k# L; F6 P+ B  create or replace procedure pc_SetVersionValid(PFlowsID in integer) is
8 k( q+ z; q* n0 A  Cursor c1 is3 F: l7 E+ y) l3 ?  n1 T* n% d
  select *
: b5 e: v: n4 Z* a3 X2 j7 y  from wf_flows
' b7 G1 c& B% R2 C  where flowname in
. ]' X/ h2 b2 N' @: h  (select flowname from wf_flows where flowsid = PFlowsID)
% O( w0 r" ^/ C4 U7 b- Q" U# g  for update;
+ P/ D/ t; ]4 M  r c1%rowtype;) p8 d5 X( x* j, p" ?  d! C1 K9 c. X
  v integer;
! b) |: L: d  J9 m  begin6 {# g9 M" A: b5 t& a2 D9 y
  open c1;( b- {* Y* ]+ O: u
  fetch c1: M5 Z" o$ k- W& Q! f8 x& y6 {! |
  into r;
7 ?) m+ V- i: y8 q  while c1%found loop" h8 S$ c5 Y  F) j
  if r.flowsid = PFlowsID then% `+ p# V( c/ X) b
  v := 1;
) a# v& r: m( ?7 `2 ~1 X  else1 V, B, a  E2 h9 G
  v := 0;
" W; v0 [4 n, w3 R( @" Z2 o4 }  end if;( g# w: `; E; t4 b; U) Q
  UPDATE wf_flows SET isValid = v WHERE CURRENT OF c1;1 G% A5 D1 u' r% Q- e& X- x
  fetch c15 `% b# r! [  s* X0 }8 n3 v
  into r;
  n2 j+ j1 R! S* {$ `  end loop;! y+ y( J8 Q8 M! e
  close c1;) S) h6 N1 s. }6 [5 F
  commit;% b$ a0 K* x/ U! q1 \
  end;: B% a- j$ f/ U4 X
  显式和隐式游标的区别:
% h. Y6 ~& q; }2 |
# Y  o$ e/ ~' Z$ w1 M' {  尽量使用隐式游标,避免编写附加的游标控制代码(声明,打开,获取,关闭),也不需要声明变量来保存从游标中获取的数据。
回复

使用道具 举报

 楼主| 发表于 2012-8-4 13:54:50 | 显示全部楼层

Oracle辅导:浅谈关于ORACLE中的游标Cursor总结(2)

</p>  2、REF CURSOR游标7 R  h7 n( K: Y
  动态游标,在运行的时候才能确定游标使用的查询。可以分为:: J& `3 _9 r( o6 s( N
  create or replace procedure TEST is
8 Q7 p# I9 a) V, P  sqlstr varchar2(500);
: Y+ {# }. G, U+ f  type RefCur is ref cursor;
- U6 P9 D5 C$ a* e5 f  c1 refcur;0 p, C: U, J) |" L
  begin
( Y3 t8 }. Z$ w  sqlstr := 'select * from tab';0 v% }" l0 \7 h1 U
  open c1 for sqlstr;5 q. V- z, ^/ z! k
  close c1;
, ?8 Q2 C  Z' b  end;
( g1 T% h8 H, K4 o/ ?. m8 C  用REF CURSOR实现BULK功能7 P; H$ D* G! {) n/ f
  1. 可以加速INSERT, UPDATE, DELETE语句的执行,也就是用FORALL语句来替代循环语句。! ^( K4 }2 U% i0 C0 o$ B1 t0 v/ z
  2. 加速SELECT,用BULK COLLECT INTO 来替代INTO。
3 ]) K% {2 F& |/ X; o3 l( M& X  SQL> create table tab2  as select empno ID, ename NAME, sal SALARY from emp where 1=2;6 A, ^) j$ m# d% U$ K% @+ V
  create or replace procedure REF_BULK is
9 ^6 \% n+ ]1 X  /*  定义复杂类型 */
  G9 ~: c8 s" H, o' |; E6 q  type empcurtyp  is ref cursor;+ q8 j7 M6 G0 `2 B* i3 P( C
  type idlist  is table of emp.empno%type;# }. E  a. i6 _. I/ u, E2 e
  type namelist  is table of emp.ename%type;
- m4 K( G8 J* W, w  type sallist  is table of emp.sal%type;
& k/ T/ v- X) m, |: m3 a4 Z5 {/ E  /* 定义变量  */
! O& |+ o& W! e: m  emp_cv  empcurtyp;
) l# Z* ?! ]3 u( ~8 H; X  ids  idlist;* N, Q$ a. {6 q' B& Y+ {4 O
  names namelist;
- T! r* B5 f/ i' t, X  sals sallist;
/ B4 T- Q, F  A% ?+ a  [  row_cnt number;& T' a) ?8 q2 a. ]  c
  begin7 g1 _, C% ~' o8 ^' `) p
  open emp_cv for select empno, ename, sal from emp;
+ d- W1 M! y7 Z0 ^( X, V: P  fetch emp_cv  BULK COLLECT  INTO ids, names, sals;
3 O& }# Y; W3 }  m6 E  --将字段成批放入变量中,此时变量是一个集合
6 r8 d3 o, _6 V  close emp_cv;
; ~: d8 c# T8 p* [. l  for i in ids.first .. ids.last loop
/ q3 M+ N( h8 H2 D  dbms_output.put_line(' || ids(i) || ' || names(i) ||' salary=' || sals(i));. `5 O/ ^: F3 ?" O' v; x+ c
  end loop;- ^! O, n1 g. ~; Z; g0 Z0 ~
  FORALL  i  IN  ids.first .. ids.last# E5 x( F3 H3 V  h2 V
  insert into tab2 values (ids(i), names(i), sals(i));; M' z8 H& y& r/ o6 `' n
  commit;
2 b4 ~( H9 w; d$ I3 [9 e  select count(*) into row_cnt from tab2;0 u; G  L2 |, e+ a9 h, p
  dbms_output.put_line('-----------------------------------');9 |9 `9 o2 R3 Y5 Y
  dbms_output.put_line('The row number of tab2 is ' || row_cnt);( @, d" }6 Z* r" X
! L; U' C7 D3 E2 Y% q% c" f
  end REF_BULK;
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-8-4 13:54:51 | 显示全部楼层

Oracle辅导:浅谈关于ORACLE中的游标Cursor总结(2)

</p>  3、cursor 和 ref cursor的区别
$ {) }3 q$ n8 d( _! t6 `  从技术底层看,两者是相同的。普通plsql cursor在定义时是“静态”的。而
* K& O7 y: x% z9 d) D  Ref cursors可以动态打开。
* B6 Z& x2 R' Z6 K& m3 s& E7 }  例如下面例子:$ C  C- y5 W6 p2 u7 X  N
  Declare9 Z/ r/ l0 Q* H$ Z1 i
  type rc is ref cursor;$ o# o# S# g$ ?$ ^7 W
  cursor c is select * from dual;; P1 j! X5 y! r9 ?( s
  l_cursor rc;0 [6 U2 s  t; b  P- r; p& x
  begin; }, T7 z" H) A5 K. A0 H' F
  if ( to_char(sysdate,'dd') = 30 ) then
6 _6 u& U# d) [3 n. e. d3 M  open l_cursor for 'select * from emp';
4 t2 U) r7 r- G. A% C7 h, H  elsif ( to_char(sysdate,'dd') = 29 ) then  n; ?* T8 F, k8 l( Y+ i
  open l_cursor for select * from dept;
+ c: n% ~1 K3 g  else! _" c+ V) s0 S
  open l_cursor for select * from dual;3 `8 ]( }- ~3 `0 D7 L2 q2 o; W: q
  end if;# o8 r+ F& Z' s) t
  open c;* B4 b0 U. J$ p* M2 Z
  end;
$ U2 _  F% }- w; ~  /- t2 \# ^2 }; |) A" F& @7 \$ T/ }
  rc根据逻辑动态打开;而游标c定义好了只有就无法修改了。2 i& B8 \5 t8 a# h# C% ?) m
  ref cursor可以返回给客户端,cursor则不行。
2 ^; r  g+ C3 g( O9 L  cursor可以是全局的global ,ref cursor则必须定义在过程或函数中。3 H3 Q8 N, t# _! |/ h, b5 i% y
  ref cursor可以在子程序间传递,cursor则不行。
8 ^; G9 y/ y, W  cursor中定义的静态sql比ref cursor效率高,所以ref cursor通常用在:向客户端返回结果集。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Woexam.Com ( 湘ICP备18023104号 )

GMT+8, 2024-6-18 12:00 , Processed in 0.502425 second(s), 26 queries .

Powered by Discuz! X3.4 Licensed

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表