PL/SQL使用游标CURSOR
一、使用游标
对于DML语句和单行select into ,oracle自动分配隐形游标。处理select返回多行语句,可以使用显式游标。
使用显示游标处理多行数据,也可使用SELECT..BULK COLLECT INTO 语句处理多行数据.
1.定义游标
cursor cursor_name is select_statement;
2.打开游标:
执行对应的SELECT语句并将SELECT语句的结果暂时存放到结果集中.
open cursor_name;
3.提取数据
打开游标后,SELECT语句的结果被临时存放到游标结果集中,使用FETCH语句只能提取一行数据
通过使用FETCH..BULK COLLECT INTO语句每次可以提取多行数据
fetch cursor_name into variable1,varibale2,...; fetch cursor_name bulk collect into collect1,collect2,...[limit rows];
(1)游标中使用fetch..into语句:只能处理一行数据,除非用循环语句
declare
v_bookname varchar2(100);
cursor c_book(i_id number) is select bookname from book where id = i_id;
begin
Open c_book(10);--打开游标
Loop
Fetch c_book into v_bookname; --提取游标
exit when c_book%notfound;
update book set price = '33' where bookname = v_bookname;
End Loop;
Close c_book;--关闭游标
end;
或
declare
v_bookname varchar2(100);
cursor c_book(i_id number) is select bookname from book where id = i_id;
begin
Open c_book(10);
Fetch c_book into v_bookname;--预先Fetch一次
While c_book%found Loop
update book set price = '33' where bookname = v_bookname;
Fetch c_book into v_bookname;
End Loop;
Close c_book;
end;
(3)基于游标定义记录变量
declare
cursor emp_cursor is select ename,sal from emp;
emp_record emp_cursor%rowtype;
begin
open emp_cursor;
loop
fetch emp_cursor into emp_record;
exit when emp_cursor%notfound;
dbms_output.put_line('雇员名:'||emp_record.ename||',雇员工资:'||emp_record.sal);
end loop;
end;
4.关闭游标
close cursor_name;
5.游标属性
用于返回显示游标的执行信息,包括%isopen,%found,%notfound,%rowcount
- %isopen:确定游标是否打开
- %found:检查是否从结果集中提取到了数据
- %notfound:与%found行为相反。
- %rowcount:返回当前行为止已经提取到的实际行数
no_data_found和%notfound的用法是有区别的,小结如下
1)SELECT. . . INTO 语句触发 no_data_found;
2)当一个显式光标(静态和动态)的 where 子句未找到时触发 %notfound;
3)当UPDATE或DELETE语句的where 子句未找到时触发 sql%notfound;
4)在光标的提取(Fetch)循环中要用 %notfound 或%found 来确定循环的退出条件,不要用no_data_found。
6.参数游标
注意:定义参数游标时,游标参数只能指定数据类型,而不能指定长度。
declare
cursor emp_cursor(no number) is select ename from emp where deptno=no;
v_ename emp.ename%type;
begin
open emp_cursor(10);
loop
fetch emp_cursor into v_ename;
exit when emp_cursor%notfound;
dbms_output.put_line(v_ename);
end loop;
close emp_cursor;
end;
二、for循环遍历,实现遍历游标最高效方式。
使用FOR循环时,ORACLE会隐含的打开游标,提取游标数据并关闭游标。
每循环一次提取一次数据,在提取了所有数据后,自动退出循环并隐含的关闭游标。
1.使用游标FOR循环
--不需要声明v_bookname,Open和Close游标和fetch操作(不用打开游标和关闭游标,实现遍历游标最高效方式)
declare
cursor c_book(i_id number) is select bookname from book where id = i_id;
begin
for cur in c_book(10) loop --循环变量cur不需要声明
update book set price = '53' where bookname = cur.bookname;
end loop;
end;
2.在游标FOR循环中直接使用子查询
begin
for emp_record in (select ename,sal from emp) loop
dbms_output.put_line(emp_record.ename);
end loop;
end;
三、使用游标更新或删除数据
要通过游标更新或删除数据,在定义游标时必须要带有FOR UPDATE子句
cursor cursor_name(parameter_name datetype) is select_statement for update [of column_reference] [nowait];
- for update子句:用于在游标结果集数据上家行共享锁,防止其他用户在相应行执行DML操作
- of子句:确定哪些表要加锁,没有OF子句,则在所引用的全部表上加锁
- nowait子句:用于指定不等待锁
- 必须在UPDATE后DELETE语句中引用WHERE CURRENT OF子句
update table_name set column=.. where current of cursor_name;
delete table_name where current of cursor_name;
declare
cursor emp_cursor is select ename,sal from emp for update;
v_ename emp.ename%type;
v_sal emp.sal%tyep;
begin
open emp_cursor;
loop
fetch emp_cursor into v_ename,v_oldsal;
exit when emp_cursor%notfound;
if v_oldsal<2000 then
update emp set sal=sal+100 where current of emp_cursor;--delete from emp where current of emp_cursor;
end if;
end loop;
close emp_cursor;
end;
四、通过bulk collect减少loop处理的开销
将查询结果一次性加载到集合中,而不是一条一条的加载。
(1)在显示游标中,使用FETCH..BALK COLLECT INTO语句提取所有数据
declare
cursor emp_cursor is select ename from emp where deptno=10;
type ename_table_type is table of varchar2(10);
ename_table ename_table_type;
begin
open emp_cursor;
fetch emp_cursor bulk collect into ename_table;
for i in 1..ename_table.count loop
dbms_output.put_line(ename_table(i));
end loop;
close emp_cursor;
end;
(2)游标中使用FETCH..BULK COLLECT INTO ..LIMIT语句提取部分数据
declare
type name_array_type is varray(5) of varchar2(10);
name_array name_array_type;
cursor emp_cursor is select ename from emp;
rows int:=5;
v_count int:=0;
begin
open emp_cursor;
loop
fetch emp_cursor bulk collect into name_array limit rows;
dbms_output.pur('雇员名');
for i in 1..(emp_currsor%rowcount-v_count) loop
dbms_output.put(name_array(i)||' ');
end loop;
dbms_output.new_line;
v_count:=emp_cursor%rowcount;
exit when emp_cursor%notfound;
end loop;
close emp_cursor;
end;
五、使用游标变量
PL/SQL的游标变量中存放着指向内存地址的指针.
1.游标变量使用步骤
包括定义游标变量,打开游标,提取游标数据,关闭游标等四个阶段
1.1定义ref cursor类型和游标变量
type ref_type_name is ref cursor [return return_type]; cursor_varibale ref_type_name;
当指定RETURN子句时,其数据类型必须是记录类型,不能在包内定义游标变量
1.2打开游标
open cursor_variable for select_statement;
1.3提取游标数据
fetch cursor_varibale into variable1,variable2,...; fetch cursor_varibale bulk collect into collect1,collect2,...[limit rows]
1.4关闭游标变量
close cursor_varibale;
2.游标变量使用示例
1、在定义FEF CURSOR类型时不指定RETURN子句
在打开游标时可以指定任何的SELECT语句
declare
type emp_cursor_type is ref cursor;
emp_cursor emp_cursor_type;
emp_record emp%rowtype;
begin
open emp_cursor for select * from emp where deptno=10;
loop
fetch emp_cursor into emp_record;
exit when emp_cursor%notfound;
dbms_output.put_line('第'||emp_curosr%rowcount||'个雇员: '||emp_record.ename);
end loop;
close emp_cursor;
end;
2、在定义REF CURSOR类型时指定RETURN子句
在打开游标时SELECT语句的返回结果必须与RETURN子句所指定的记录类型相匹配.
declare
type emp_record_type is record(name varchar2(10),salary number(6,2));
type emp_cursor_type is ref cursor return emp_record_type;
emp_cursor emp_cursor_type;
emp_record emp_record_type;
begin
open emp_cursor for select ename,sal from emp where deptno=20;
loop
fetch emp_cursor into emp_record;
exit when emp_cursor%notfound;
dbms_output.put_line('第'||emp_curosr%rowcount||'个雇员: '||emp_record.ename);
end loop;
close emp_cursor;
end;
PL/SQL使用游标CURSOR的更多相关文章
- PL/SQL 04 游标 cursor
--游标 declare cursor 游标名字 is 查询语句;begin 其他语句;end; --游标的属性%FOUND%NOTFOUND%ISOPEN%ROWCOUNT(当前游标的指针位 ...
- PL/SQL之--游标
一.游标简介 在PL/SQL中执行SELECT.INSERT.DELETE和UPDATE语句时,ORACLE会在内存中为其分配上下文区(Context Area),也称为缓冲区.游标是指向该区的一个指 ...
- Oracle PL/SQL,游标,过程
1.PL/SQL 语法相关 -- SQL 语言只是访问,操作数据库的语言,而比并不是程序设计语言,因此不能用于程序开发. -- PL/SQL 是在标准SQl语言上进行过程性扩展后形成的程序设计语言, ...
- orcale 之 PL/SQL的游标
根据我们之前了解到的情况,SQL是面向集合的,我们的查询结果一般包含多条数据,而在PL/SQL 中的变量一般只能存放一条数据,因此变量是无法满足我们的需求的.这时候我们就需要引入游标来为我们解决问题了 ...
- PL/SQL之游标的使用
Oracle中的游标有两种: 显式游标 用CURSOR...IS 命令定义的游标,它可以对查询语句(SELECT)返回的多条记录进行处理. 隐式游标 是在执行插入(INSERT).删除(DELETE) ...
- PL/SQL编程—游标
一.游标的相关概念: 定义: 游标它是一个服务器端的存储区,这个区域提供给用户使用,在这个区域里 存储的是用户通过一个查询语句得到的结果集,用户通过控制这个游标区域当中 的指针 来提取游标中的数据,然 ...
- 在PL/SQL使用游标获取数据及动态SQL
1.游标概念: 当在PL/SQL块中执行DML(增删改)时,Oracle会为其分配上下文区(Context Area),游标是指向上下文区的指针 2. 游标分类: A. 隐式游标 a. 在PL/ ...
- Oracle pl/sql 显示游标和隐式游标
显示游标 一.定义语法: CURSOR <游标名> IS <SELECT 语句> [FOR UPDATE | FOR UPDATE ...
- 学习使用MS SQL Server游标(CURSOR)
说实的,使用MS SQL Server这样久,游标一直没有使用过.以前实现相似的功能,都是使用WHILE循环加临时表来实现.刚才有参考网上示例练习写了一下.了解到游标概念与语法. 下面代码示例中,先是 ...
随机推荐
- php实现文件与16进制相互转换
php实现文件与16进制相互转换 <pre><?php/** * php 文件与16进制相互转换 * Date: 2017-01-14 * Author: fdipzone * Ve ...
- php面相对象类中成员
类中成员 一个类的内部可以有3种代码:属性.方法.类常量它们统称为“类中成员”. 一般属性 属性就是放在一个类中的变量. 定义形式: 形式1: var $v1 ; //定义不赋值 形式2: var ...
- 软件素材---C/C++格式化显示当前时间--标准函数strftime
函数原型:size_t strftime (char* ptr, size_t maxsize, const char* format,const struct tm* timeptr ); 头文件: ...
- PHP与Memcached服务器交互的分布式实现源码分析
转自: http://blog.csdn.net/hguisu/article/details/7353595 前段时间,因为一个项目的关系,研究了php通过调用memcache和memcached ...
- 在CentOS下搭建GoLang开发环境
下载安装包 [vagrant@dk ~]$ wget http://mirrors.ustc.edu.cn/golang/go1.13.linux-amd64.tar.gz 使用USTC 中科大开源镜 ...
- Zuul【入门】
1.创建eureka-server注册中心工程,配置跟之前讲eureka文章中一样,这里不再赘述 1.1.端口8888 2.创建一个demo-client工程 2.1.demo-client启动类跟之 ...
- PAT(B) 1089 狼人杀-简单版(Java)逻辑推理
题目链接:1089 狼人杀-简单版 (20 point(s)) 题目描述 以下文字摘自<灵机一动·好玩的数学>:"狼人杀"游戏分为狼人.好人两大阵营.在一局" ...
- The 2018 ACM-ICPC Asia Nanjing Regional Programming Contest
A. Adrien and Austin 大意: $n$个石子, 编号$1$到$n$, 两人轮流操作, 每次删除$1$到$k$个编号连续的石子, 不能操作则输, 求最后胜负情况. 删除一段后变成两堆, ...
- MySQL 5.7使用xtabackup报错解决
报错信息: InnoDB: An optimized (without redo logging) DDLoperation has been performed. All modified page ...
- RabbitMQ的应用场景
进入正题. 一.异步处理 场景:发送手机验证码,邮件 传统古老处理方式如下图 这个流程,全部在主线程完成,注册->入库->发送邮件->发送短信,由于都在主线程,所以要等待每一步完成才 ...