CURSOR

说明

隐式游标

隐式游标是一个会话级别的游标,由PL/SQL构建和管理,当运行一个SELECT或DML语句时,默认打开一个隐式游标,不能控制隐式游标,但可以从其属性中获得相关信息。

隐式游标的属性语法称之为SQLattribute,因此隐式游标也称作SQL游标。SQLattribute通常指向最近运行的SELECT或DML语句,如果没有该语句运行,则值为NULL。

隐式游标当其关联的语句运行完后将会关闭,然而其属性值在另一个SELECT或DML语句运行前仍然可用。

要保存当前隐式游标属性值以供以后使用,需要将其分配给局部变量,否则,其他操作(如子程序调用)可能会在测试属性之前更改属性的值。

其中各个参数选项如下所示:

  • %ISOPE

隐式游标是否打开,bool值,总是false。

  • %FOUND

存在以下情况:

  • 如果没有SELECT或DML语句执行返回NULL
  • 如果最近的SELECT和DML语句返回一行或多行返回true
  • 如果最近的SELECT 和DML语句没有返回行返回false
  • %NOTFOUND

存在以下情况:

  • 如果没有SELECT或DML语句执行返回NULL
  • 如果最近的SELECT和DML语句返回一行或多行返回false
  • 如果最近的SELECT和DML语句没有返回行则返回true
  • %ROWCOUNT

存在以下情况:

  • 如果没有SELECT 或DML语句执行返回NULL
  • 如果有SELECT或DML语句执行则返回当前被获取的行数

显式游标

一个显示游标是一个会话级别的游标,它由用户来构建和管理,可以声明和定义一个显示游标,给显示游标一个名字并将其和一个查询关联,你可以用如下方式处理该查询的结果。

  • 使用open语句打开显示游标,使用fetch语句获取查询中的行,以及使用close关闭显示游标
  • 在FOR LOOP语句中使用显示游标

游标变量及操作

要创建一个游标变量,可以以预定义类型SYS_REFCURSOR定义变量或者定义一个REF CURSOR类型,然后以该类型定义变量。

游标变量限制:

  • 不能在包规范中定义游标变量
  • 集合中或数据库的列中不能存储游标变量的值
  • 不能使用比较运算符测试游标变量是否相等、不相等或无效
  • 在服务器端到服务器远程过程调用(RPC)中使用游标变量会导致错误

OPEN FOR操作

在定义好游标变量后,可以使用OPEN FOR语句来打开它,在重新打开游标变量之前,不需要关闭它,在你重新打开游标变量之后,之前和它关联的查询将会丢失。

FETCH操作

当打开一个游标变量后,可以使用FETCH语句来从结果集中获取行数据。

给游标变量赋值

可以将一个PL/SQL游标变量的值赋值给另一个PL/SQL 游标变量或者host 游标变量。

命名游标属性

显示游标和游标变量都有一个名字与其关联,因此统称命名游标,每个命名游标都有四个属性,这些属性返回关于执行DML或SLEECT操作的信息。

  • Named_cursor
  • Explicit_cursor:显示游标的名字
  • Cursor_parameter:游标类型的参数名字
  • Cursor_variable:游标变量的名字
  • :host_cursor_variable:主机变量

其中Named_cursor_attribute包括如下:

  • %ISOPEN

如果cursor被打开,则返回TRUE,否则返回FALSE。

  • %FOUND

存在如下值:

  • 游标没打开,则报INVALID_CURSOR异常
  • 游标打开了,但没有进行FETCH,NULL
  • 最近的FETCH 返回行了,TRUE
  • 最近的FETCH没有返回一行,FALSE
  • %NOTFOUND

存在如下值:

  • 游标没打开,抛出INVALID_CURSOR异常
  • 游标打开,没有FETCH操作,NULL
  • 最近的FETCH返回行数据,FALSE
  • 最近的FETCH没有返回行数据,TRUE
  • %ROWCOUNT

存在如下值:

  • 游标没有打开,抛出INVALID_CURSOR异常
  • 游标已经打开,当前fetch出来的行数的值

示例

-- 创建一个示例表并插入一些数据

CREATE TABLE employees (

employee_id NUMBER PRIMARY KEY,

first_name VARCHAR2(50),

last_name VARCHAR2(50),

salary NUMBER

);

INSERT INTO employees (employee_id, first_name, last_name, salary) VALUES (1, ‘John’, ‘Doe’, 60000);

INSERT INTO employees (employee_id, first_name, last_name, salary) VALUES (2, ‘Jane’, ‘Smith’, 75000);

INSERT INTO employees (employee_id, first_name, last_name, salary) VALUES (3, ‘Alice’, ‘Johnson’, 90000);

INSERT INTO employees (employee_id, first_name, last_name, salary) VALUES (4, ‘Bob’, ‘Brown’, 50000);

DECLARE CURSOR emp_cursor IS SELECT employee_id, first_name, last_name, salary FROM employees where employee_id=1;

emp_record emp_cursor%ROWTYPE;

BEGIN

OPEN emp_cursor;

LOOP

FETCH emp_cursor INTO emp_record;

EXIT WHEN emp_cursor%NOTFOUND;

raise notice ‘ID: %, Name: % %, Salary: %’, emp_record.employee_id ,emp_record.first_name,emp_record.last_name,emp_record.salary;

END LOOP;

CLOSE emp_cursor;

END;

/