PL/SQL之--游标
一、游标简介
在PL/SQL中执行SELECT、INSERT、DELETE和UPDATE语句时,ORACLE会在内存中为其分配上下文区(Context Area),也称为缓冲区。游标是指向该区的一个指针。它提供了一种在多行结果集中对每一行数据分别进行单独处理的方法。用户可以用SQL语句逐一从游标中获取记录,并赋给主变量,交由主语言进一步处理。
oracle中游标有如下两种:
- 静态游标:分为显式游标和隐式游标。
- ref游标:引用类型,类似于C中的指针。
二、静态游标
静态游标分为显式游标和隐式游标,静态游标在编译的时候已经确定,然后把结果复制到内存中。
1、隐式游标
在PL/SQL中执行数据操作语句查询(查询一行),修改,删除(DML语句)时,oracle预先定义一个名称为SQL的隐式游标,在执行DML语句之后通过检查隐式游标的属性获取与最近执行的SQL语句相关信息。用户只能通过隐式游标的相关属性,从而完成相应的操作。在隐式游标的工作区中,所存放的数据是与用户自定义的显示游标无关的、最新处理的一条SQL 语句所包含的数据。
调用语法为:SQL%
隐式游标属性%found、%notfound、%rowcount、%isopen这四种,详情如下:
- %found: 只有DML语句影响一行或多行时,%found属性才返回true;
- %notfound: 如果DML语句没有影响任何行数,则%notfound返回true;
- %rowcount: 返回DML影响的行数,如果DML没有影响任何行数,则%rowcount返回0;
- %isopen: 判断SQL游标是否已经打开,在执行SQL语句之后,oracle会自动关闭SQL游标,所有隐式游标的%isopen属性始终为false;
当PL/SQL抛出异常的时候,将不使用属性%found、%notfound、%rowcount来查明DML语句是否已经影响了行数。
代码示例如下:
select中使用隐式游标
-- select隐式游标
declare
v_id number := 1;
v_username varchar2(255);
v_age number;
v_password varchar2(255);
begin
select username, age, password into v_username, v_age, v_password from person where id = v_id;
dbms_output.put_line(SQL%ROWCOUNT);--影响的行数
if SQL%ISOPEN then
dbms_output.put_line('open');
else
dbms_output.put_line('not open');
end if; if SQL%FOUND then --成功
dbms_output.put_line('found');
else --失败
dbms_output.put_line('not found');
end if; if SQL%NOTFOUND then --失败
dbms_output.put_line('not found');
else --成功
dbms_output.put_line('found');
end if;
end;
insert中的隐式游标
-- insert 隐式游标
declare
v_id number := 26;
v_username varchar2(255) := 'xiaoming';
v_age number := 19;
v_password varchar2(255) := 'xiao123' ;
begin
insert into person (id, username, age, password) values (v_id, v_username, v_age, v_password);
-- commit; --此时commit后面都会没有值
dbms_output.put_line(SQL%ROWCOUNT);--增加的行数
if SQL%ISOPEN then
dbms_output.put_line('open');
else
dbms_output.put_line('not open');
end if; if SQL%FOUND then --成功
dbms_output.put_line('found');
else --失败
dbms_output.put_line('not found');
end if; if SQL%NOTFOUND then --失败
dbms_output.put_line('not found');
else --成功
dbms_output.put_line('found');
end if;
-- commit;
end;
update中使用隐式游标
-- update 隐式游标
declare
v_id number := 25;
v_age number := 100;
begin
update person set age = v_age where id = v_id;
--commit; --此时commit后面都会没有值
dbms_output.put_line(SQL%ROWCOUNT);--修改的行数
if SQL%ISOPEN then
dbms_output.put_line('open');
else
dbms_output.put_line('not open');
end if; if SQL%FOUND then --成功
dbms_output.put_line('found');
else --失败
dbms_output.put_line('not found');
end if; if SQL%NOTFOUND then --失败
dbms_output.put_line('not found');
else --成功
dbms_output.put_line('found');
end if;
commit;
end;
delete中使用隐式游标
-- delete 隐式游标
declare
v_id number := 26;
begin
delete from person where id = v_id;
-- commit; --此时commit后面都会没有值
dbms_output.put_line(SQL%ROWCOUNT);--删除的行数
if SQL%ISOPEN then
dbms_output.put_line('open');
else
dbms_output.put_line('not open');
end if; if SQL%FOUND then --成功
dbms_output.put_line('found');
else --失败
dbms_output.put_line('not found');
end if; if SQL%NOTFOUND then --失败
dbms_output.put_line('not found');
else --成功
dbms_output.put_line('found');
end if;
commit;
end;
2、显式游标
显示游标时由用户显示声明的游标。根据在游标中定义的查询,查询返回的行集合可以包括0行货多行,这些行称为活动集。游标将指向活动集中的当前行。
显示游标的操作过程如下:
1)、定义游标
CURSOR 游标名称 is 查询语句;
CURSOR 游标名称[参数1,参数2、...]
[RETURN 数据类型]
IS
查询语句;
游标参数只能为输入参数,格式为:
参数名称 [IN] 数据类型 [值]
2)、打开游标
open 游标名称 [参数名称 => 值, 参数名称 => 值,..];
3)、从游标中获取结果集
FETCH 游标名称 INTO 变量;
执行FETCH语句时,每次返回一条数据行,并自动将游标移动指向下一条数据行。当检索到最后一条数据时,如果再次执行FETCH语句,操作将失败,游标属性%NOTFOUND设置为TRUE。所以每次执行完FETCH语句后,检查游标属性%NOTFOUND就从而判断FETCH语句是否执行成功并返回一个数据行,确定是否为最后一行。
4)、关闭游标
CLOSE 游标名称;
显式游标属性如下:
- %FOUND 布尔型属性,当最近一次提取游标操作FETCH成功则为 TRUE,否则为FALSE;
- %NOTFOUND 布尔型属性,与%FOUND相反;
- %ISOPEN 布尔型属性,当游标已打开时返回 TRUE;
- %ROWCOUNT 数字型属性,返回已从游标中读取的记录数;
代码示例如下:
不带参数不带返回值的游标
-- 不带参数的游标不带返回值的游标
declare
-- 1、定义一个游标,将person所有数据提取出来
cursor c_person is
select * from person;
r_person person%rowtype;
begin
--2、打开游标
open c_person;
--3、提取数据
loop
fetch c_person
into r_person;
exit when c_person%notfound; -- 下面没有数据的时候,退出
dbms_output.put_line('id:'||r_person.id);
dbms_output.put_line('username:'||r_person.username);
dbms_output.put_line('age:'||r_person.age); end loop;
--4、关闭游标
close c_person;
end;
带参数不带返回值的游标
--带参数不带返回值的游标
declare
-- 1、定义一个游标,将person所有数据提取出来
cursor c_person(v_age number) is
select * from person where age < v_age;
r_person person%rowtype;
begin
--2、打开游标
open c_person(20);--打开游标,传递参数值
--3、提取数据
loop
fetch c_person
into r_person;
exit when c_person%notfound; -- 下面没有数据的时候,退出
dbms_output.put_line('id:'||r_person.id);
dbms_output.put_line('username:'||r_person.username);
dbms_output.put_line('age:'||r_person.age); end loop;
--4、关闭游标
close c_person;
end;
带参数带返回值的游标,返回type类型
-- 带参数带返回值的游标,返回type类型
declare
r_person person%rowtype; -- 1、定义一个游标,有参数和返回值
cursor c_person(v_age number)
return person%rowtype
is
select * from person where age < v_age;
begin
--2、打开游标
open c_person(20);--打开游标,传递参数值
--3、提取数据
loop
fetch c_person
into r_person;
exit when c_person%notfound; -- 下面没有数据的时候,退出
dbms_output.put_line('id:'||r_person.id);
dbms_output.put_line('username:'||r_person.username);
dbms_output.put_line('age:'||r_person.age);
dbms_output.put_line('password:'||r_person.password); end loop;
--4、关闭游标
close c_person;
end;
带参数带返回值的游标,返回自定义类型
-- 带参数带返回值的游标,返回自定义类型
declare
type person_record_type is record(
t_username person.username%type,
t_age person.age%type,
t_password person.password%type
);
v_person_record person_record_type; -- 1、定义一个游标,有参数和返回值
cursor c_person(v_age number)
return person_record_type
is
select username, age, password from person where age < v_age;
begin
--2、打开游标
open c_person(20);--打开游标,传递参数值
--3、提取数据
loop
fetch c_person
into v_person_record;
exit when c_person%notfound; -- 下面没有数据的时候,退出
dbms_output.put_line('username:'||v_person_record.t_username);
dbms_output.put_line('age:'||v_person_record.t_age);
dbms_output.put_line('password:'||v_person_record.t_password); end loop;
--4、关闭游标
close c_person;
end;
三、ref 类型游标
ref游标也是一个指向多行查询结果集合中当前数据行的指针。但与游标不同的是,ref游标是动态的,而游标是静态的。隐式游标和显示游标都是静态定义的。它们在编译的时候结果集就已经被确定。而ref游标在运行时候可以指向不同查询语句的结果集。 定义游标变量类型,可以采用强类型定义和弱类型定义两种。强类型定义必须指定游标变量的返回值类型,而弱类型定义则定义说明返回值类型。
语法如下:
1、定义一个REF CURSOU 数据类型
type 游标名称 IS REF CURSOR
return 返回类型;
2、声明一个该数据类型的游标变量,如:
游标变量名称 游标名称;
示例代码如下:
ref 类型游标弱类型(无返回值)
-- ref 类型游标弱类型(无返回值)
declare
type c_person_type is ref cursor;
c_person c_person_type;
r_person person%rowtype;
begin
-- 遍历person表
open c_person for select * from person_back;--person_back与person表结构一样
loop
fetch c_person
into r_person;
exit when c_person%notfound; -- 下面没有数据的时候,退出
dbms_output.put_line('id:'||r_person.id);
dbms_output.put_line('username:'||r_person.username);
dbms_output.put_line('age:'||r_person.age);
end loop;
--关闭游标
dbms_output.put_line('---------------------------------');
-- 变量person_back
open c_person for select * from person;
loop
fetch c_person
into r_person;
exit when c_person%notfound; -- 下面没有数据的时候,退出
dbms_output.put_line('id:'||r_person.id);
dbms_output.put_line('username:'||r_person.username);
dbms_output.put_line('age:'||r_person.age);
end loop;
close c_person;
end;
ref 类型游标强类型(返回row type)
-- ref 类型游标强类型(返回row type)
declare
type c_persontype is ref cursor return person%rowtype;
c_person c_persontype;
r_person person%rowtype;
begin
-- 遍历person表
open c_person for select * from person;
loop
fetch c_person
into r_person;
exit when c_person%notfound; -- 下面没有数据的时候,退出
dbms_output.put_line('id:'||r_person.id);
dbms_output.put_line('username:'||r_person.username);
dbms_output.put_line('age:'||r_person.age);
end loop;
close c_person;
dbms_output.put_line('--------------------------------------');
-- 遍历person_back表
open c_person for select * from person_back;
loop
fetch c_person
into r_person;
exit when c_person%notfound; -- 下面没有数据的时候,退出
dbms_output.put_line('id:'||r_person.id);
dbms_output.put_line('username:'||r_person.username);
dbms_output.put_line('age:'||r_person.age);
end loop;
close c_person;
end;
-- ref 类型游标强类型(返回自定义类型)
-- ref 类型游标强类型(返回自定义类型)
declare
-- 定义一个数据类型
type person_record is record(
username varchar2(255), -- 定义好长度,否则会保持
age number,
password varchar2(255)
);
-- 定义返回自定义数据类型的游标类型
type c_persontype is ref cursor return person_record;
c_person c_persontype; -- 游标类型的变量
r_person person_record; -- 自定义数据类型变量
begin
-- 遍历person表
open c_person for select username, age, password from person;
loop
fetch c_person
into r_person;
exit when c_person%notfound; -- 下面没有数据的时候,退出
dbms_output.put_line('username:'||r_person.username);
dbms_output.put_line('age:'||r_person.age);
dbms_output.put_line('password:'||r_person.password);
end loop;
close c_person;
dbms_output.put_line('--------------------------------------');
-- 遍历person_back表
open c_person for select username, age, password from person_back;
loop
fetch c_person
into r_person;
exit when c_person%notfound; -- 下面没有数据的时候,退出
dbms_output.put_line('username:'||r_person.username);
dbms_output.put_line('age:'||r_person.age);
dbms_output.put_line('password:'||r_person.password);
end loop;
close c_person;
end;
sys_refcursor
sys_refcursor是oracle9i以后系统定义的一个refcursor,主要用在过程中返回结果集。我们也可以直接使用sys_refcursor遍历结果集。
示例代码如下:
declare
c_person sys_refcursor;
r_person person%rowtype;
begin
-- 遍历person表
open c_person for select * from person_back;--person_back与person表结构一样
loop
fetch c_person
into r_person;
exit when c_person%notfound; -- 下面没有数据的时候,退出
dbms_output.put_line('id:'||r_person.id);
dbms_output.put_line('username:'||r_person.username);
dbms_output.put_line('age:'||r_person.age);
end loop;
--关闭游标
dbms_output.put_line('---------------------------------');
-- 变量person_back
open c_person for select * from person;
loop
fetch c_person
into r_person;
exit when c_person%notfound; -- 下面没有数据的时候,退出
dbms_output.put_line('id:'||r_person.id);
dbms_output.put_line('username:'||r_person.username);
dbms_output.put_line('age:'||r_person.age);
end loop;
close c_person;
end;
PL/SQL之--游标的更多相关文章
- PL/SQL使用游标CURSOR
一.使用游标 对于DML语句和单行select into ,oracle自动分配隐形游标.处理select返回多行语句,可以使用显式游标. 使用显示游标处理多行数据,也可使用SELECT..BULK ...
- 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 04 游标 cursor
--游标 declare cursor 游标名字 is 查询语句;begin 其他语句;end; --游标的属性%FOUND%NOTFOUND%ISOPEN%ROWCOUNT(当前游标的指针位 ...
- 在PL/SQL使用游标获取数据及动态SQL
1.游标概念: 当在PL/SQL块中执行DML(增删改)时,Oracle会为其分配上下文区(Context Area),游标是指向上下文区的指针 2. 游标分类: A. 隐式游标 a. 在PL/ ...
- Oracle pl/sql 显示游标和隐式游标
显示游标 一.定义语法: CURSOR <游标名> IS <SELECT 语句> [FOR UPDATE | FOR UPDATE ...
- Oracle_PL/SQL(3) 游标
引言:PLSQL数据类型标量数据类型:数字类.字符类.日期类.布尔类(boolean).复合数据类型:记录(%rowtype).表.数组引用类型:REF CURSORLOB类型:BLOB.CLOB 1 ...
随机推荐
- Const的用法
宏和const的区别: 1.宏执行的是替换操作,这也就意味着会在内存中开辟多个临时空间 这样显然不是很好 2.宏不可以修改 const : 用const修饰的变量 为常量 不能修改,在内存中只有一份内 ...
- Python入门笔记(17):错误、异常
一.什么是错误,什么是异常,它们两者区别 这里解释如下:个人觉得很通俗易懂 错误是指在执行代码过程中发生的事件,它中断或干扰代码的正常流程并创建异常对象.当错误中断流程时,该程序将尝试寻找异常处理程序 ...
- 单例(C#版)
单例: 一个类只有一个实例.巧妙利用了编程语言的一些语法规则:构造函数private, 然后提供一个public的方法返回类的一个实例:又方法和返回的类的实例都是static类型,所以只能被类所拥有, ...
- C# ICSharpCode.SharpZipLib.dll文件压缩和解压功能类整理,上传文件或下载文件很常用
工作中我们很多时候需要进行对文件进行压缩,比较通用的压缩的dll就是ICSharpCode.SharpZipLib.dll,废话不多了,网上也有很多的资料,我将其最常用的两个函数整理了一下,提供了一个 ...
- csharp:Chart
http://www.dotnetperls.com/chart using System; using System.Windows.Forms; using System.Windows.Form ...
- 批量导数据之利器-load data[2016-07-11]
由于天热,中午吃完饭后不再去逛了,感觉这段时间其实也是可以利用起来的,所以决定每天中午积累一些小的知识点.今天中午,先总结一下最近造数据用到手命令,load data. 使用这个命令的起源是因为最近要 ...
- phpcms—— 内容中的附件调用和添加远程地址的调用
phpcms中几个地址调用的方法 1,CSS路径有{CSS_PATH}2,图片路径有{IMG_PATH}3,JS路径有{JS_PATH} 4,那么附件的路径如何调用,使用下面的方式可以得到附件的路径前 ...
- YUIDoc example代码高亮错误、生成API文档目录不按源文件注释顺序
1.如果发现yuidoc命令用不了,那就重装nodejs吧 昨天不知道是清扫电脑的原因,yuidoc命令用不了(命令不存在),也没有找到好的解决方法,怒重装YUIDoc也不行.最后想了想,怒重装了no ...
- Javascript面向对象编程(三) --- 非构造函数的继承
一.什么是"非构造函数"的继承? 比如,现在有一个对象,叫做"中国人". var Chinese = { nation:'中国' }; 还有一个对象,叫做&qu ...
- angularjs的双向数据绑定
数据绑定有两个方向: 数据 → 界面:我们使用scope对象的$watch()方法监听数据的变化,来更新界面. <html> <head> <title>监听数据& ...