a我考网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 193|回复: 2

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

[复制链接]
发表于 2012-8-4 13:54:49 | 显示全部楼层 |阅读模式
1.4 游标的更新和删除   在PL/SQL中依然可以使用UPDATE和DELETE语句更新或删除数据行。显式游标只有在需要获得多行数据的情况下使用。PL/SQL提供了仅仅使用游标就可以执行删除或更新记录的方法。& W% T+ G6 M7 t0 Y  D6 a& t7 i
  UPDATE或DELETE语句中的WHERE CURRENT OF子串专门处理要执行UPDATE或DELETE操作的表中取出的最近的数据。要使用这个方法,在声明游标时必须使用FOR UPDATE子串,当对话使用FOR UPDATE子串打开一个游标时,所有返回集中的数据行都将处于行级(ROW-LEVEL)独占式锁定,其他对象只能查询这些数据行,不能进行 UPDATE、DELETE或SELECT...FOR UPDATE操作。
3 A" X- x1 \. N4 t! {8 Y1 B: T  在多表查询中,使用OF子句来锁定特定的表,如果忽略了OF子句,那么所有表中选择的数据行都将被锁定。如果这些数据行已经被其他会话锁定,那么正常情况下ORACLE将等待,直到数据行解锁。
6 V$ P8 d" v% E0 \$ M& Z4 S  在UPDATE和DELETE中使用WHERE CURRENT OF子串的语法如下:7 g, R, \8 _; T- Y$ ?: h
  WHERE{CURRENT OF cursor_name|search_condition}1 I! a! s9 h2 N2 I& W3 Z% z- Z
  例:3 W6 [' I6 I- e9 w
  create or replace procedure pc_SetVersionValid(PFlowsID in integer) is7 T! |4 p# _$ t  y
  Cursor c1 is
7 k! z. g. s/ G% X# o  select *
+ P  h* w4 M. f1 g3 n8 r7 n  from wf_flows# ^% U: H: l+ f/ |
  where flowname in3 t8 @4 `: q2 D' y# ^! ~
  (select flowname from wf_flows where flowsid = PFlowsID)
, C2 G, g! ^: O2 t, {9 S  for update;
! |7 I# K& {- X4 y# F" k. z7 \6 \  r c1%rowtype;' X/ l4 ~/ }" x6 h( g
  v integer;
+ F* \7 E2 `: r( E8 M9 Y  begin# L* v$ d: a0 ~5 q. |
  open c1;; k! A# ?  K7 V; e  E* B# m3 l! C
  fetch c1& b' w& B* {9 @& C/ u" r
  into r;$ T$ I# G: ~0 m) [' g
  while c1%found loop
3 e% r1 a( n, n1 c- R  if r.flowsid = PFlowsID then
8 Z8 j( ?3 I0 _, O; j- X) u  v := 1;
6 S" V& r& p7 L4 ~) r  else0 Y+ k2 r1 ~& l, y0 j9 Q
  v := 0;& H0 q6 ?* Q# I: w
  end if;
0 q4 Q# z( a, B2 X% t3 N6 j) t: C  UPDATE wf_flows SET isValid = v WHERE CURRENT OF c1;; V0 s- }! i7 H8 l/ |# v  d
  fetch c1$ n8 x7 `& a* m
  into r;6 V" U0 [8 f& p% A
  end loop;
. }4 m7 T; Q' r' d' Y+ Y- e" _( i9 W  close c1;
' @. U4 l0 o0 I* j0 ^  commit;
/ ^9 H( K8 N) B1 o  end;
: B" C  R! y5 g  显式和隐式游标的区别:
/ V+ p% ~8 @- f1 g/ }# S1 O$ O# z/ q6 e2 j( i5 _' M+ f2 ]
  尽量使用隐式游标,避免编写附加的游标控制代码(声明,打开,获取,关闭),也不需要声明变量来保存从游标中获取的数据。
回复

使用道具 举报

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

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

</p>  2、REF CURSOR游标
, J6 k2 R/ D2 V. F- v3 }: `  动态游标,在运行的时候才能确定游标使用的查询。可以分为:
/ x% M: K( p% h2 {8 [+ E  create or replace procedure TEST is: a* p' Z9 ?6 q
  sqlstr varchar2(500);1 F. z$ p& q3 q& h+ _3 D* B5 A
  type RefCur is ref cursor;% }, t" L, p1 S& q5 o! ^8 u; I
  c1 refcur;
" V/ H3 P$ Q- Q, v8 K/ L  begin2 h- H7 _+ O5 [( R% ?8 I- \8 o
  sqlstr := 'select * from tab';* q: j+ f8 }$ p; F
  open c1 for sqlstr;
! s, @0 m. K+ O8 c+ X7 ^- d  close c1;
5 ^3 s1 D/ l4 x& B4 |  end;
% k. {" W, a  y* N' [. o+ ?* F  用REF CURSOR实现BULK功能/ U, g# ]* i. u/ A. r1 R! m
  1. 可以加速INSERT, UPDATE, DELETE语句的执行,也就是用FORALL语句来替代循环语句。0 y6 X2 h% y% I2 q7 J0 p
  2. 加速SELECT,用BULK COLLECT INTO 来替代INTO。. p& F6 A2 Q8 j; V/ o
  SQL> create table tab2  as select empno ID, ename NAME, sal SALARY from emp where 1=2;3 \0 t: c( p# x7 A
  create or replace procedure REF_BULK is9 X: `7 ]6 \  M1 t2 u
  /*  定义复杂类型 */
, y6 x/ z& e' M) o6 \! {  type empcurtyp  is ref cursor;
; d, |6 T0 z# r& }- G  type idlist  is table of emp.empno%type;
) t- k0 d3 H. L/ q' i  type namelist  is table of emp.ename%type;; W! d9 E$ }& j4 {8 W, z
  type sallist  is table of emp.sal%type;
% f& a. T$ S; b+ z  /* 定义变量  */
8 S% e- ^  Q$ \+ P" v  emp_cv  empcurtyp;
* C  B% K" y9 {" D" q  ids  idlist;- K; E1 v/ Z! m, K) c. C1 p) F
  names namelist;
9 d$ S8 L- a3 X) K+ O8 r; ?  sals sallist;' ~2 U' s6 }% W
  row_cnt number;, m+ k  ~4 c; r" z
  begin
$ Y4 B. {5 p8 M  open emp_cv for select empno, ename, sal from emp;0 U' N* D% Y* T+ a/ u
  fetch emp_cv  BULK COLLECT  INTO ids, names, sals;  @% @; ^  B3 Y% x
  --将字段成批放入变量中,此时变量是一个集合
) s$ e& n3 ^/ a: z6 J3 l  close emp_cv;
2 e; y* B1 [. }8 W. U; ~+ @, ^0 K4 z( Q  for i in ids.first .. ids.last loop" F+ g) e7 A3 J3 E8 j
  dbms_output.put_line(' || ids(i) || ' || names(i) ||' salary=' || sals(i));
8 m. s6 h4 O! }* s' [$ I  end loop;0 Y" j, C) |$ o1 U) }. O
  FORALL  i  IN  ids.first .. ids.last
- [3 E/ o. V4 W( r8 \  insert into tab2 values (ids(i), names(i), sals(i));
7 @, \: _* b# h  commit;
+ @9 X, {* u+ a- Y  select count(*) into row_cnt from tab2;
! ~4 L) l2 |& D, Y  dbms_output.put_line('-----------------------------------');
- B/ b- c0 [% V0 A7 I  dbms_output.put_line('The row number of tab2 is ' || row_cnt);
6 A  m: K3 h( w( c, q2 M
. ?' s4 c, C5 |8 D7 j  end REF_BULK;
回复 支持 反对

使用道具 举报

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

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

</p>  3、cursor 和 ref cursor的区别* Q( j  V$ ~% B& |/ _' J
  从技术底层看,两者是相同的。普通plsql cursor在定义时是“静态”的。而1 S% H2 f' v9 F5 G5 \# d
  Ref cursors可以动态打开。
2 m7 G1 N8 Y7 @/ c  例如下面例子:/ e; Y. v. M) F) N1 r  i* _& Z  E
  Declare
& K0 a1 ~7 m3 L  type rc is ref cursor;
5 D2 n$ E4 O1 F! }0 G  cursor c is select * from dual;& [! c% b+ F9 \$ N
  l_cursor rc;  |8 O3 g* z2 v: i% d0 ~
  begin* ~# Z! p! D- d0 D
  if ( to_char(sysdate,'dd') = 30 ) then! b, N# Y" ]% T4 O+ ?
  open l_cursor for 'select * from emp';9 n7 q8 S- G7 W' G. O
  elsif ( to_char(sysdate,'dd') = 29 ) then( B! v  y+ H; v. ^
  open l_cursor for select * from dept;
0 L, M! }/ z4 A, D  else
, L* r2 q0 L8 C7 k% i- k( |# J+ f  open l_cursor for select * from dual;
' }( I) p5 p) a  end if;1 V; p/ C4 X3 N5 w
  open c;
0 c7 x3 m0 ~: X  end;  x1 l: Y+ M& [; K% q; i2 H# v
  /- \8 j. Z' ]& Z
  rc根据逻辑动态打开;而游标c定义好了只有就无法修改了。& q/ T) y7 I3 P6 D0 v% g) R
  ref cursor可以返回给客户端,cursor则不行。
' U7 y' \5 K$ K- ~  cursor可以是全局的global ,ref cursor则必须定义在过程或函数中。$ ^- s& K- ^8 L8 b
  ref cursor可以在子程序间传递,cursor则不行。
) o3 J- K' g# d$ R- ~$ w  cursor中定义的静态sql比ref cursor效率高,所以ref cursor通常用在:向客户端返回结果集。
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-5-23 00:59 , Processed in 0.181408 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

© 2001-2017 Comsenz Inc.

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