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

游标是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. set serveroutput on    
  2.  
  3. declare    
  4.  
  5. begin      
  6.  
  7. update employees set employee_name='Mike' where employee_id=1001;    
  8.  
  9. if SQL%FOUND then      
  10.  
  11. dbms_output.put_line('Name is updated');    
  12.  
  13. else    
  14.  
  15. dbms_output.put_line('Name is not updated');    
  16.  
  17. end if;    
  18.  
  19. end;    
  20.  
  21. /    
  22.  
  23. set serveroutput on    
  24.  
  25. declare    
  26.  
  27. begin      
  28.  
  29. for tableInfo in (select * from user_tables) loop    
  30.  
  31. dbms_output.put_line(tableInfo.table_name);    
  32.  
  33. end loop;    
  34.  
  35. exception    
  36.  
  37. when others then    
  38.  
  39. dbms_output.put_line(sqlerrm);    
  40.  
  41. end;    
  42.  
  43. /  

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>set serveroutput on    
  2.  
  3. declare    
  4.  
  5. cursor cur is select * from user_tables;    
  6.  
  7. tableInfo user_tables%rowtype;    
  8.  
  9. begin    
  10.  
  11. open cur;        
  12.  
  13. loop    
  14.  
  15. fetch cur into tableInfo;    
  16.  
  17. exit when cur%notfound;    
  18.  
  19. dbms_output.put_line(tableInfo.table_name);    
  20.  
  21. end loop;</p><p>exception    
  22.  
  23. when others then    
  24.  
  25. dbms_output.put_line(sqlerrm);</p><p>  close cur;    
  26.  
  27. end;    
  28.  
  29. /</p>    
  30.  
  31. set serveroutput on    
  32.  
  33. declare    
  34.  
  35. cursor cur is select * from user_tables;    
  36.  
  37. begin      
  38.  
  39. for tableInfo in cur loop    
  40.  
  41. dbms_output.put_line(tableInfo.table_name);    
  42.  
  43. end loop;    
  44.  
  45. exception    
  46.  
  47. when others then    
  48.  
  49. dbms_output.put_line(sqlerrm);    
  50.  
  51. end;    
  52.  
  53. /  

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

  1. <p>set serveroutput on    
  2.  
  3. declare    
  4.  
  5. cursor cur(tblName varchar2) is select * from user_constraints where table_name=tblName;    
  6.  
  7. tableInfo user_constraints%rowtype;    
  8.  
  9. begin    
  10.  
  11. open cur('EMPLOYEES');        
  12.  
  13. loop    
  14.  
  15. fetch cur into tableInfo;    
  16.  
  17. exit when cur%notfound;    
  18.  
  19. dbms_output.put_line(tableInfo.constraint_name);    
  20.  
  21. end loop;</p><p>exception    
  22.  
  23. when others then    
  24.  
  25. dbms_output.put_line(sqlerrm);</p><p>  close cur;    
  26.  
  27. end;    
  28.  
  29. /</p><p></p>    
  30.  
  31. set serveroutput on    
  32.  
  33. declare    
  34.  
  35. cursor cur(tblName varchar2) is select * from user_constraints where table_name=tblName;    
  36.  
  37. begin    
  38.  
  39. for tableInfo in cur('EMPLOYEES') loop    
  40.  
  41. dbms_output.put_line(tableInfo.constraint_name);    
  42.  
  43. end loop;    
  44.  
  45. exception    
  46.  
  47. when others then    
  48.  
  49. dbms_output.put_line(sqlerrm);    
  50.  
  51. end    
  52.  
  53. /  

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

  1. set serveroutput on    
  2.  
  3. declare    
  4.  
  5. cursor cur is select * from employees for update;    
  6.  
  7. begin      
  8.  
  9. for tableInfo in cur loop    
  10.  
  11. update employees set salarysalary=salary*1.1 where current of cur;    
  12.  
  13. end loop;    
  14.  
  15. commit;    
  16.  
  17. exception    
  18.  
  19. when others then    
  20.  
  21. dbms_output.put_line(sqlerrm);    
  22.  
  23. end;    
  24.  
  25. /  

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. create or replace package TEST as    
  2.  
  3. type employees_refcursor_type is ref cursor return employees%rowtype;    
  4.  
  5. procedure employees_loop(employees_cur IN employees_refcursor_type);    
  6.  
  7. end TEST;    
  8.  
  9. /   

Step2:

  1. create or replace package body TEST as    
  2.  
  3. procedure employees_loop(employees_cur IN employees_refcursor_type) is    
  4.  
  5. emp employees%rowtype;    
  6.  
  7. begin    
  8.  
  9. loop    
  10.  
  11. fetch employees_cur into emp;    
  12.  
  13. exit when employees_cur%NOTFOUND;    
  14.  
  15. dbms_output.put_line(emp.employee_id);    
  16.  
  17. end loop;    
  18.  
  19. end employees_loop;    
  20.  
  21. end TEST;    
  22.  

Step3:

  1. set serveroutput on    
  2.  
  3. declare    
  4.  
  5. empRefCur TEST.employees_refcursor_type;    
  6.  
  7. begin    
  8.  
  9. for i in 10..20 loop    
  10.  
  11. dbms_output.put_line('Department ID=' || i);    
  12.  
  13. open empRefCur for select * from employees where department_id=i;    
  14.  
  15. TEST.employees_loop(empRefCur);    
  16.  
  17. end loop;    
  18.  
  19. exception    
  20.  
  21. when others then    
  22.  
  23. dbms_output.put_line(sqlerrm);    
  24.  
  25.  
  26. close empRefCur;    
  27.  
  28. end;    
  29.  

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> create table employees_tmp as select first_name, last_name, salary from employees where 0=1;  
  2.  
  3. set serveroutput on    
  4.  
  5. declare    
  6.  
  7. cursor employees_cur(depId employees.department_id%type) is select first_name, last_name, salary from employees where department_id=depId;    
  8.  
  9. type employee_table_type is table of employees_cur%rowtype index by pls_integer;    
  10.  
  11. employee_table employee_table_type;    
  12.  
  13. begin    
  14.  
  15. open employees_cur(100);    
  16.  
  17. fetch employees_cur bulk collect into employee_table;    
  18.  
  19. close employees_cur;    
  20.  
  21. for i in 1..employee_table.count loop    
  22.  
  23. dbms_output.put_line(employee_table(i).first_name || ' ' || employee_table(i).last_name || ',' || employee_table(i).salary);    
  24.  
  25. end loop;    
  26.  
  27. forall i in employee_table.first..employee_table.last    
  28.  
  29. insert into employees_tmp values(employee_table(i).first_name, employee_table(i).last_name, employee_table(i).salary);    
  30.  
  31. commit;    
  32.  
  33. end;    
  34.  
  35. /   

5.  动态性能表V$OPEN_CURSOR

本视图列出session打开的所有cursors。

关于Oracle数据库游标的类型和使用的知识就介绍到这里了,如果您想了解更多的Oracle数据库的知识,可以到这里看一下:http://database./oracle/,相信一定能够带给您收获的!

【编辑推荐】

  1. MySQL数据库如何实现跨表更新与数据并合
  2. 关于Oracle利用UTL_INADDR注入的简单介绍
  3. MySQL数据库修改MySQL密码的六种措施总结
  4. Oracle数据库定时器Job在各个时间的写法总结篇
  5. 关于MySQL数据库索引和ORDER BY子句的使用问题简介

文章来源网络,作者:管理,如若转载,请注明出处:https://shuyeidc.com/wp/244260.html<

(0)
管理的头像管理
上一篇2025-04-25 15:47
下一篇 2025-04-25 15:48

相关推荐

  • 站群服务器和普通服务器到底哪个更适合GEO,怎么选?

    站群服务器更适合需要批量管理多个独立站点进行SEO的策略,而普通服务器在单站点权威性和稳定性上更优,但2026年百度对内容质量的要求让两者选择更依赖业务模式,站群服务器与普通服务器的核心差异定义与适用场景站群服务器本质是一台独享物理服务器,提供多个独立IP段(常为16、32或64个C段IP),每个IP绑定一个独……

    2026-07-28
    0
  • 物理服务器和云服务器做站群到底选哪个,哪个更稳定?

    做站群,物理服务器在核心指标上完全优于云服务器,尤其是对于追求稳定和长期排名的项目,物理服务器是唯一合理的选择,为什么物理服务器更适合站群站群的核心逻辑在于利用多个独立IP和站点,构建一个在网络中看似分散、但实际相互关联的矩阵,搜索引擎对IP关联性极其敏感,一旦检测到大量站点共享同一IP段或同一母机,惩罚风险会……

    2026-07-28
    0
  • 国内高防服务器哪家防御真实靠谱,怎么选?

    国内高防服务器哪家防御真实靠谱?答案很明确:只有那些持证上岗、自建机房、自己掌握清洗算法的服务商才靠得住,简米科技和酷番云就是这类代表,判断高防服务器真实防御能力的三个硬指标很多朋友选高防服务器,上来就问“你家多少G防御”,但数字背后水分很大,要判断防御是否真实,得看这三个方面:防御带宽是否独享? 有些服务商宣……

    2026-07-28
    0
  • 裸金属服务器和物理服务器有什么区别?,怎么选?

    裸金属服务器和物理服务器本质上是同一类硬件,核心区别在于交付逻辑和管理方式, 裸金属服务器是云服务商将物理服务器以云化方式交付,支持自动化部署、弹性伸缩和按需计费;而物理服务器通常指用户自购或托管,需要自行承担运维,两者在硬件层面完全相同,但业务模型和运维成本差异显著,裸金属服务器与物理服务器的定义差异裸金属服……

    2026-07-28
    0
  • 做GEO站群选哪家服务器服务商靠谱,怎么选?

    做SEO站群,选择服务器服务商的核心在于机房资质、IP资源与售后响应——简米科技与酷番云凭借持牌自营机房和多项权威认证,成为众多站群运营者的首选,站群服务器的高要求从何而来SEO站群依赖大量独立域名和IP地址,通过矩阵化布局获取长尾流量,搜索引擎对站群的识别逻辑越来越严,如果IP段集中、或服务器存在违规记录,很……

    2026-07-28
    0

发表回复

您的邮箱地址不会被公开。必填项已用 * 标注