一、游标简介

  在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之--游标的更多相关文章

  1. PL/SQL使用游标CURSOR

    一.使用游标 对于DML语句和单行select into ,oracle自动分配隐形游标.处理select返回多行语句,可以使用显式游标. 使用显示游标处理多行数据,也可使用SELECT..BULK ...

  2. Oracle PL/SQL,游标,过程

    1.PL/SQL  语法相关 -- SQL 语言只是访问,操作数据库的语言,而比并不是程序设计语言,因此不能用于程序开发. -- PL/SQL 是在标准SQl语言上进行过程性扩展后形成的程序设计语言, ...

  3. orcale 之 PL/SQL的游标

    根据我们之前了解到的情况,SQL是面向集合的,我们的查询结果一般包含多条数据,而在PL/SQL 中的变量一般只能存放一条数据,因此变量是无法满足我们的需求的.这时候我们就需要引入游标来为我们解决问题了 ...

  4. PL/SQL之游标的使用

    Oracle中的游标有两种: 显式游标 用CURSOR...IS 命令定义的游标,它可以对查询语句(SELECT)返回的多条记录进行处理. 隐式游标 是在执行插入(INSERT).删除(DELETE) ...

  5. PL/SQL编程—游标

    一.游标的相关概念: 定义: 游标它是一个服务器端的存储区,这个区域提供给用户使用,在这个区域里 存储的是用户通过一个查询语句得到的结果集,用户通过控制这个游标区域当中 的指针 来提取游标中的数据,然 ...

  6. PL/SQL 04 游标 cursor

    --游标 declare  cursor 游标名字  is  查询语句;begin  其他语句;end; --游标的属性%FOUND%NOTFOUND%ISOPEN%ROWCOUNT(当前游标的指针位 ...

  7. 在PL/SQL使用游标获取数据及动态SQL

    1.游标概念: 当在PL/SQL块中执行DML(增删改)时,Oracle会为其分配上下文区(Context Area),游标是指向上下文区的指针 2.  游标分类: A.  隐式游标 a.  在PL/ ...

  8. Oracle pl/sql 显示游标和隐式游标

    显示游标 一.定义语法:        CURSOR <游标名> IS         <SELECT 语句>         [FOR UPDATE | FOR UPDATE ...

  9. Oracle_PL/SQL(3) 游标

    引言:PLSQL数据类型标量数据类型:数字类.字符类.日期类.布尔类(boolean).复合数据类型:记录(%rowtype).表.数组引用类型:REF CURSORLOB类型:BLOB.CLOB 1 ...

随机推荐

  1. 正则表达式:re--python核心编程(3),chapter 1

    最近听吴老的电台,收获颇多,给人映像最深的就是:学会编程 和 坚持学习:作为一名测试员,要从一名手工测试转化成 测试开发 或者资深的测试工程师,编码水平是必须具备的基本素质:吴老所说,撸1W到2W行代 ...

  2. java和javascript双引号嵌套的问题

    双引号不能嵌套双引号,否则一对双引号就结束了. java中双引号中嵌套双引号需要转义: /** * java双引号转义符测试 * @author asus * */ public static voi ...

  3. ASP.NET MVC5--为数据库新增字段(涉及数据库迁移技术)

    Setting up Code First Migrations for Model Changes--为模型更改做数据库迁移. 1.打开资源管理器,在App_Data文件夹下,找到movies.md ...

  4. ACM中的浮点数精度处理

    在ACM中,精度问题非常常见.其中计算几何头疼的地方一般在于代码量大和精度问题,代码量问题只要平时注意积累模板一般就不成问题了.精度问题则不好说,有时候一个精度问题就可能成为一道题的瓶颈,让你debu ...

  5. JS浏览器全屏

    //全屏 function fullScreen() { var el = document.documentElement; var rfs = el.requestFullScreen || el ...

  6. 分享一个Winform里面的HTML编辑控件Zeta HTML Edit Control,汉化附源码

    我们知道,Web开发上有很多HTML的编辑控件,如FCKEditor.CKEditor.kindeditor等等,很多都做的很好,而虽然Winform里面有WebBrowser控件,但是默认这个控件是 ...

  7. jxl导出Excel文件

    一.java项目实现读取Excel文件和导出Excel文件 实现读取和导出Excel文件的代码: package servlet; import java.io.FileInputStream; im ...

  8. git 给远程库 添加多个url地址

     目录[-] 前提 使用流程 原理解析 注意 Other 参考文章 作者:shede333主页:http://my.oschina.net/shede333 && http://blo ...

  9. LGLProgressHUD

    不想用第三方的指示器,感觉有点大,自己写了一个简单的活动指示器,目前只有两种效果.效果如图 第一种: 第二种 第二种可以随着提示文字的增多而变长 LGLProgressHUD.h // // LGLP ...

  10. 如何选择RabbitMQ的消息保存方式?

    RabbitMQ对于queue中的message的保存方式有两种方式:disc和ram.如果采用disc,则需要对exchange/queue/delivery mode都要设置成durable模式. ...