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;
时间: 2024-10-13 11:37:47

PL/SQL之--游标的相关文章

orcale 之 PL/SQL的游标

根据我们之前了解到的情况,SQL是面向集合的,我们的查询结果一般包含多条数据,而在PL/SQL 中的变量一般只能存放一条数据,因此变量是无法满足我们的需求的.这时候我们就需要引入游标来为我们解决问题了. 我们知道在 PL/SQL 中可以使用数据控制语言(DML)对数据进行操作,而在使用这些的时候 Orcale 会在内存中为其分配一个缓存区.而游标就是指向该缓存区的指针.它可以对查询结果集的每一行数据分别进行单独的处理. 游标分为显式游标和隐式游标.显式游标是由用户声明操作的一种游标,而隐式游标是

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

1.游标概念: 当在PL/SQL块中执行DML(增删改)时,Oracle会为其分配上下文区(Context Area),游标是指向上下文区的指针 2.  游标分类: A.  隐式游标 a.  在PL/SQL中使用DML语句时自动创建隐式游标 b.  隐式游标自动声明.打开和关闭,其名为 SQL c.  通过检查隐式游标的属性可以获得最近执行的DML 语句的信息 d.  隐式游标的属性有: %FOUND – SQL 语句影响了一行或多行时为 TRUE %NOTFOUND – SQL 语句没有影响任

PL/SQL 04 游标 cursor

--游标 declare  cursor 游标名字  is  查询语句;begin  其他语句;end; --游标的属性%FOUND%NOTFOUND%ISOPEN%ROWCOUNT(当前游标的指针位移量) --FETCH的两种形式FETCH cursor_name INTO var1, var2, -;FETCH cursor_name INTO record_var; --游标的FETCH循环LOOP  FETCH cursor INTO-  EXIT WHEN cursor%NOTFOUN

oracle pl/sql之游标

前情提要: 在通过select语句查询是,返回的结果通常是多行记录组成的集合.为此SQL提供 了游标机制.游标可以充当指针的作用,使应用程序设计语言一次只能处理查询记过中的一行.在Oracle中,可以使用隐式和显示两种游标.在pl/sql 中程序所有发出的DML和select语句,Oracle都会自动声明“隐式游标”.为了处理由select语句返回的一组记录,需要在pl/sql程序中申明和处理“显示游标”. 隐式游标 游标的主要属性如下: %found 布尔型属性,如果SQL语句至少影响一行,则

Oracle数据库PL/SQL存储过程游标触发器

创建一个添加FOOD的存储过程 create or replace procedure add_food_pro (name in varchar,price in number,description in varchar) as  begin insert into food (f_name,f_price,description)values(name,price,description); commit; end; --下面的代码是调用存储过程 begin add_food_pro('糖

[Oracle系列整理04] oracle pl/sql 基础

PL/SQL块中只能直接嵌入SELECT,DML(INSERT,UPDATE,DELETE)以及事务控制语句 (COMMIT,ROLLBACK,SAVEPOINT),而不能直接嵌入DDL语句(CREATE,ALTER,DROP)和DCL语句 (GRANT,REVOKE) 1.检索单行数据    1.1使用标量变量接受数据  v_ename emp.ename%type;  v_sal   emp.sal%type;  select ename,sal into v_ename,v_sal fro

PL/SQL详细介绍,设置oracle相关

1. 实现参照完整性      指若两个表之间具有主从关系(即主外键关系),当删除主表数据时,必须确保相关的从表数据已经被删除.  当修改主表的主键列数据时,必须确保相关从表数据已经被修改.为了实现级联删除,可在定义外部键约束时指定ON DELETE CASCADE关键字  alter table emp add constraint fk_deptno foreign key (deptno) references dept(deptno) on delete cascade; 实现级联更新,

数据库复习10——PL/SQL

数据库复习 CH10 PL/SQL 10.1 PL/SQL简介 PL/SQL是Oracle对SQL的过程化的扩展,PL/SQL可以实现SQL相关的过程化程序,并且能够以存储过程和函数的方式让一段SQL业务逻辑驻留在SQL服务器中,以便减少客户机计算任务并减少网络I/O 10.2 PL/SQL编程基础 (1)简介 PL/SQL编程框架为: DECLARE <Variable List> BEGIN <Extented SQL Execution> EXCEPTION <Exce

Oracle_PL/SQL(3) 游标

引言:PLSQL数据类型标量数据类型:数字类.字符类.日期类.布尔类(boolean).复合数据类型:记录(%rowtype).表.数组引用类型:REF CURSORLOB类型:BLOB.CLOB 1.系统定义的记录:%rowtype使用%rowtype属性定义记录变量:可以基于表或视图定义记录变量当使用%ROWTYPE属性定义记录变量时,记录成员个数,名称,类型与表或视图列的个数, 名称,类型完全相同. 1.1 在select语句中使用PL/SQL记录declare v_emp emp%row