Oracle会创建一个存储区域,被称为上下文区域,用于处理SQL语句,其中包含需要处理的语句,例如所有的信息,行数处理,等等。
游标是指向这一上下文的区域。 PL/SQL通过控制光标在上下文区域。游标持有的行(一个或多个)由SQL语句返回。行集合光标保持的被称为活动集合。
可以命名一个光标,它可以在程序中获取和处理SQL语句,一次返回的行引用。有两种类型的游标:
- 
隐式游标 
- 
显式游标 
隐式游标
Oracle在一个SQL语句的执行,当没有显式游标的语句隐式游标时自动创建。程序员无法控制隐式游标其中的信息。
每当发出一个DML语句(INSERT,UPDATE和DELETE),隐式游标与此语句关联。对于INSERT操作时,光标保持一个需要插入的数据。对于UPDATE和DELETE操作,光标标识会受到影响的行。
在PL/SQL,可以参考最近的隐式游标的SQL游标,它有类似%FOUND,%ISOPEN,%NOTFOUND,和%ROWCOUNT属性。在SQL游标有额外的属性,%BULK_ROWCOUNT和%BULK_EXCEPTIONS,设计用于所有语句中使用。下表提供了最常用的属性的描述:
| 属性 | 描述 | 
|---|---|
| %FOUND | 返回TRUE如果一个INSERT,UPDATE或DELETE语句影响了一行或多行或SELECT INTO语句返回一行或多行。否则,它将返回FALSE。 | 
| %NOTFOUND | 逻辑相反%FOUND。返回TRUE如果一个INSERT,UPDATE或DELETE语句影响没有行或SELECT INTO语句返回任何行。否则,它将返回FALSE。 | 
| %ISOPEN | 隐式游标总是返回FALSE,因为Oracle执行其相关的SQL语句之后自动关闭SQL游标。 | 
| %ROWCOUNT | 返回受INSERT,UPDATE影响的行数,或DELETE语句,或者通过一个SELECT INTO语句返回。 | 
任何SQL游标属性将被访问,SQL%attribute_name如示例图所示。
例子:
这里使用我们已经创建,并在前面的章节中使用的CUSTOMERS表。
Select * from customers;
+----+----------+-----+-----------+----------+
| ID | NAME     | AGE | ADDRESS   | SALARY   |
+----+----------+-----+-----------+----------+
|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 |
|  2 | Khilan   |  25 | Delhi     |  1500.00 |
|  3 | kaushik  |  23 | Kota      |  2000.00 |
|  4 | Chaitali |  25 | Mumbai    |  6500.00 |
|  5 | Hardik   |  27 | Bhopal    |  8500.00 |
|  6 | Komal    |  22 | MP        |  4500.00 |
+----+----------+-----+-----------+----------+
下面的程序将更新表,并通过每个客户的薪水增加500和使用SQL%ROWCOUNT属性来确定受影响的行数:
DECLARE 
   total_rows number(2);
BEGIN
   UPDATE customers
   SET salary = salary + 500;
   IF sql%notfound THEN
      dbms_output.put_line(‘no customers selected‘);
   ELSIF sql%found THEN
      total_rows := sql%rowcount;
      dbms_output.put_line( total_rows || ‘ customers selected ‘);
   END IF; 
END;
/
当上述代码在SQL提示符执行时,它产生了以下结果:
6 customers selected PL/SQL procedure successfully completed.
如果查看customers表中的记录,会发现各行已更新:
Select * from customers;
+----+----------+-----+-----------+----------+
| ID | NAME     | AGE | ADDRESS   | SALARY   |
+----+----------+-----+-----------+----------+
|  1 | Ramesh   |  32 | Ahmedabad |  2500.00 |
|  2 | Khilan   |  25 | Delhi     |  2000.00 |
|  3 | kaushik  |  23 | Kota      |  2500.00 |
|  4 | Chaitali |  25 | Mumbai    |  7000.00 |
|  5 | Hardik   |  27 | Bhopal    |  9000.00 |
|  6 | Komal    |  22 | MP        |  5000.00 |
+----+----------+-----+-----------+----------+
显式游标
显式游标是程序员定义游标获得更多的控制权的上下文的区域。显式游标应在PL/SQL块的声明部分中定义。这是创建一个SELECT语句返回多行。
创建显式游标语法是:
CURSOR cursor_name IS select_statement;
使用显式游标的工作包括四个步骤:
- 
声明游标用于初始化在存储器 
- 
打开游标分配内存 
- 
获取游标检索数据 
- 
关闭游标释放分配的内存 
声明游标
声明游标定义游标的名称和相关的SELECT语句。例如:
CURSOR c_customers IS
   SELECT id, name, address FROM customers;
打开游标
打开游标游标分配内存,使得它准备取的SQL语句转换成它返回的行。例如,我们将打开上述定义的游标如下:
OPEN c_customers;
获取游标
获取游标涉及一次访问一行。例如,将获取行从上面打开的游标,如下所示:
FETCH c_customers INTO c_id, c_name, c_addr;
关闭游标
关闭游标来释放分配的内存。例如,将关闭前面打开的游标,如下所示:
CLOSE c_customers;
例子:
下面是一个完整的例子来说明明确游标的概念:
DECLARE
   c_id customers.id%type;
   c_name customers.name%type;
   c_addr customers.address%type;
   CURSOR c_customers is
      SELECT id, name, address FROM customers;
BEGIN
   OPEN c_customers;
   LOOP
      FETCH c_customers into c_id, c_name, c_addr;
      EXIT WHEN c_customers%notfound;
      dbms_output.put_line(c_id || ‘ ‘ || c_name || ‘ ‘ || c_addr);
   END LOOP;
   CLOSE c_customers;
END;
/
当上述代码在SQL提示符执行时,它产生了以下结果:
1 Ramesh Ahmedabad 2 Khilan Delhi 3 kaushik Kota 4 Chaitali Mumbai 5 Hardik Bhopal 6 Komal MP PL/SQL procedure successfully completed.
