Oracle数据库游标的类型及使用实例全解

本文我们主要介绍了Oracle数据库的五种类型的游标的使用,这五种游标分别是:隐式游标、显式游标、REF CURSOR、BULK SQL和动态性能表V$OPEN_CURSOR,希望能够对您有所帮助。

游标是SQL的一个内存工作区,由系统或用户以变量的形式定义。游标的作用就是用于临时存储从数据库中提取的数据块。Oracle数据库的Cursor类型包含三种: 静态游标:分为显式(explicit)游标和隐式(implicit)游标;REF游标:是一种引用类型,类似于指针。下面我们一一介绍它们的使用。

1.隐式游标

1)Select …INTO…语句,DML语句,使用隐式Cursor。此外,还有一种使用FOR LOOP的Implicit Cursor用法。

2)可以通过隐式Cusor的属性来了解操作的状态和结果。Cursor的属性包含:

SQL%ROWCOUNT 整型代表DML语句成功执行的数据行数。

SQL%FOUND 布尔型值为TRUE代表插入、删除、更新或单行查询操作成功。

SQL%NOTFOUND 布尔型与SQL%FOUND属性返回值相反。

SQL%ISOPEN 布尔型DML执行过程中为真,结束后为假。

3) 隐式Cursor由系统自动打开和关闭.

例如:

 
  
  1. setserveroutputon
  2. declare
  3. begin
  4. updateemployeessetemployee_name='Mike'whereemployee_id=1001;
  5. ifSQL%FOUNDthen
  6. dbms_output.put_line('Nameisupdated');
  7. else
  8. dbms_output.put_line('Nameisnotupdated');
  9. endif;
  10. end;
  11. /
  12. setserveroutputon
  13. declare
  14. begin
  15. fortableInfoin(select*fromuser_tables)loop
  16. dbms_output.put_line(tableInfo.table_name);
  17. endloop;
  18. exception
  19. whenothersthen
  20. dbms_output.put_line(sqlerrm);
  21. end;
  22. /

2.显式游标

1) 显式Cursor的属性包含:

游标的属性 返回值类型 意义

%ROWCOUNT 整型 获得FETCH语句返回的数据行数

%FOUND 布尔型 最近的FETCH语句返回一行数据则为真,否则为假

%NOTFOUND 布尔型 与%FOUND属性返回值相反

%ISOPEN 布尔型 游标已经打开时值为真,否则为假

2) 对于显式游标的运用分为四个步骤:

a 定义游标---Cursor [Cursor Name] IS;

b 打开游标---Open [Cursor Name];

c 操作数据---Fetch [Cursor name]

d 关闭游标---Close [Cursor Name]

以下是几种常见显式Cursor用法。

 
  
  1. <p>setserveroutputon
  2. declare
  3. cursorcurisselect*fromuser_tables;
  4. tableInfouser_tables%rowtype;
  5. begin
  6. opencur;
  7. loop
  8. fetchcurintotableInfo;
  9. exitwhencur%notfound;
  10. dbms_output.put_line(tableInfo.table_name);
  11. endloop;</p><p>exception
  12. whenothersthen
  13. dbms_output.put_line(sqlerrm);</p><p>closecur;
  14. end;
  15. /</p>
  16. setserveroutputon
  17. declare
  18. cursorcurisselect*fromuser_tables;
  19. begin
  20. fortableInfoincurloop
  21. dbms_output.put_line(tableInfo.table_name);
  22. endloop;
  23. exception
  24. whenothersthen
  25. dbms_output.put_line(sqlerrm);
  26. end;
  27. /

还可以使用带参数open的cursor。

 
  
  1. <p>setserveroutputon
  2. declare
  3. cursorcur(tblNamevarchar2)isselect*fromuser_constraintswheretable_name=tblName;
  4. tableInfouser_constraints%rowtype;
  5. begin
  6. opencur('EMPLOYEES');
  7. loop
  8. fetchcurintotableInfo;
  9. exitwhencur%notfound;
  10. dbms_output.put_line(tableInfo.constraint_name);
  11. endloop;</p><p>exception
  12. whenothersthen
  13. dbms_output.put_line(sqlerrm);</p><p>closecur;
  14. end;
  15. /</p><p></p>
  16. setserveroutputon
  17. declare
  18. cursorcur(tblNamevarchar2)isselect*fromuser_constraintswheretable_name=tblName;
  19. begin
  20. fortableInfoincur('EMPLOYEES')loop
  21. dbms_output.put_line(tableInfo.constraint_name);
  22. endloop;
  23. exception
  24. whenothersthen
  25. dbms_output.put_line(sqlerrm);
  26. end
  27. /

可以使用WHERE CURRENT OF子句执行UPDATE或DELETE操作。

 
  
  1. setserveroutputon
  2. declare
  3. cursorcurisselect*fromemployeesforupdate;
  4. begin
  5. fortableInfoincurloop
  6. updateemployeessetsalarysalary=salary*1.1wherecurrentofcur;
  7. endloop;
  8. commit;
  9. exception
  10. whenothersthen
  11. dbms_output.put_line(sqlerrm);
  12. end;
  13. /

3.REF CURSOR(Cursor Variables)

REF Cursor在运行的时候才能确定游标使用的查询。利用REF CURSOR,可以在程序间传递结果集(一个程序里打开游标变量,在另外的程序里处理数据)。

也可以利用REF CURSOR实现BULK SQL,提高SQL性能。

REF CURSOR分两种,Strong REF CURSOR 和 Weak REF CURSOR。

Strong REF CURSOR:指定retrun type,CURSOR变量的类型必须和return type一致。

Weak REF CURSOR:不指定return type,能和任何类型的CURSOR变量匹配。

Ref cursor的使用:

1) Type [Cursor type name] is ref cursor

2) Open cursor for...

3) Fetch [Cursor name]

4) Close Cursor

例如:

Step1:

 
  
  1. createorreplacepackageTESTas
  2. typeemployees_refcursor_typeisrefcursorreturnemployees%rowtype;
  3. procedureemployees_loop(employees_curINemployees_refcursor_type);
  4. endTEST;
  5. /

Step2:

 
  
  1. createorreplacepackagebodyTESTas
  2. procedureemployees_loop(employees_curINemployees_refcursor_type)is
  3. empemployees%rowtype;
  4. begin
  5. loop
  6. fetchemployees_curintoemp;
  7. exitwhenemployees_cur%NOTFOUND;
  8. dbms_output.put_line(emp.employee_id);
  9. endloop;
  10. endemployees_loop;
  11. endTEST;
  12. /

Step3:

 
  
  1. setserveroutputon
  2. declare
  3. empRefCurTEST.employees_refcursor_type;
  4. begin
  5. foriin10..20loop
  6. dbms_output.put_line('DepartmentID='||i);
  7. openempRefCurforselect*fromemployeeswheredepartment_id=i;
  8. TEST.employees_loop(empRefCur);
  9. endloop;
  10. exception
  11. whenothersthen
  12. dbms_output.put_line(sqlerrm);
  13. closeempRefCur;
  14. end;
  15. /

4.BULK SQL

使用FORALL和BULK COLLECT子句。利用BULK SQL可以减少PLSQL Engine和SQL Engine之间的通信开销,提高性能。

1. To speed up INSERT, UPDATE, and DELETE statements, enclose the SQL statement within a PL/SQL FORALL statement instead of a loop construct. 加速INSERT, UPDATE, DELETE语句的执行,也就是用FORALL语句来替代循环语句。

2. To speed up SELECT statements, include the BULK COLLECT INTO clause in the SELECT statement instead of using INTO. 加速SELECT,用BULK COLLECT INTO 来替代INTO。

 
  
  1. SQL>createtableemployees_tmpasselectfirst_name,last_name,salaryfromemployeeswhere0=1;
  2. setserveroutputon
  3. declare
  4. cursoremployees_cur(depIdemployees.department_id%type)isselectfirst_name,last_name,salaryfromemployeeswheredepartment_id=depId;
  5. typeemployee_table_typeistableofemployees_cur%rowtypeindexbypls_integer;
  6. employee_tableemployee_table_type;
  7. begin
  8. openemployees_cur(100);
  9. fetchemployees_curbulkcollectintoemployee_table;
  10. closeemployees_cur;
  11. foriin1..employee_table.countloop
  12. dbms_output.put_line(employee_table(i).first_name||''||employee_table(i).last_name||','||employee_table(i).salary);
  13. endloop;
  14. foralliinemployee_table.first..employee_table.last
  15. insertintoemployees_tmpvalues(employee_table(i).first_name,employee_table(i).last_name,employee_table(i).salary);
  16. commit;
  17. end;
  18. /
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值