📜  PL / SQL cursor

📅  最后修改于: 2020-11-12 01:54:17             🧑  作者: Mango

PL / SQL游标

处理SQL语句时,Oracle将创建一个称为上下文区域的内存区域。光标是指向此上下文区域的指针。它包含处理语句所需的所有信息。在PL / SQL中,上下文区域由Cursor控制。游标包含有关select语句和它所访问的数据行的信息。

游标用于引用程序,一次读取和处理SQL语句返回的行。游标有两种类型:

  • 隐式游标
  • 显式游标

1)PL / SQL隐式游标

如果您不对语句使用显式游标,则隐式游标由Oracle在执行SQL语句时自动生成。

默认情况下创建这些语句,以在执行INSERT,UPDATE,DELETE等DML语句时处理语句。

Orcale提供了一些称为“隐式游标”属性的属性,以检查DML操作的状态。其中一些是:%FOUND,%NOTFOUND,%ROWCOUNT和%ISOPEN。

例如:当您执行INSERT,UPDATE,DELETE之类的SQL语句时,游标属性会告诉您是否影响了任何行以及影响了多少行。如果在PL / SQL块中运行SELECT INTO语句,则隐式游标属性可用于查找SELECT语句是否返回了任何行。如果没有选择任何数据,它将返回一个错误。

下表通过其每个属性来区分游标的状态。

Attribute Description
%FOUND Its return value is TRUE if DML statements like INSERT, DELETE and UPDATE affect at least one row or more rows or a SELECT INTO statement returned one or more rows. Otherwise it returns FALSE.
%NOTFOUND Its return value is TRUE if DML statements like INSERT, DELETE and UPDATE affect no row, or a SELECT INTO statement return no rows. Otherwise it returns FALSE. It is a just opposite of %FOUND.
%ISOPEN It always returns FALSE for implicit cursors, because the SQL cursor is automatically closed after executing its associated SQL statements.
%ROWCOUNT It returns the number of rows affected by DML statements like INSERT, DELETE, and UPDATE or returned by a SELECT INTO statement.

PL / SQL隐式游标示例

创建客户表并有记录:

ID NAME AGE ADDRESS SALARY
1 Ramesh 23 Allahabad 20000
2 Suresh 22 Kanpur 22000
3 Mahesh 24 Ghaziabad 24000
4 Chandan 25 Noida 26000
5 Alex 21 Paris 28000
6 Sunita 20 Delhi 30000

让我们执行以下程序来更新表并将每个客户的薪水提高5000。在这里,SQL%ROWCOUNT属性用于确定受影响的行数:

创建过程:

DECLARE 
   total_rows number(2);
BEGIN
   UPDATE  customers
   SET salary = salary + 5000;
   IF sql%notfound THEN
      dbms_output.put_line('no customers updated');
   ELSIF sql%found THEN
      total_rows := sql%rowcount;
      dbms_output.put_line( total_rows || ' customers updated ');
   END IF; 
END;
/

输出:

现在,如果您检查客户表中的记录,您会发现行已更新。

select * from customers;
ID NAME AGE ADDRESS SALARY
1 Ramesh 23 Allahabad 25000
2 Suresh 22 Kanpur 27000
3 Mahesh 24 Ghaziabad 29000
4 Chandan 25 Noida 31000
5 Alex 21 Paris 33000
6 Sunita 20 Delhi 35000

2)PL / SQL显式游标

显式游标由程序员定义,以获取对上下文区域的更多控制。这些游标应在PL / SQL块的声明部分中定义。它是在SELECT语句上创建的,该语句返回多个行。

显式游标的语法

以下是创建显式游标的语法:

CURSOR cursor_name IS select_statement;;

脚步:

使用显式游标时,必须遵循以下步骤。

  • 声明光标以在内存中初始化。
  • 打开游标以分配内存。
  • 获取光标以检索数据。
  • 关闭游标以释放分配的内存。

1)声明光标:

它使用名称和关联的SELECT语句定义游标。

显式游标清理的语法

CURSOR name IS
 SELECT statement; 

2)打开光标:

它用于为游标分配内存,并使其易于将SQL语句返回的行读取到其中。

游标打开的语法:

OPEN cursor_name;

3)获取游标:

它用于一次访问一行。您可以按如下所示从上述打开的游标中获取行:

游标提取的语法:

FETCH cursor_name INTO variable_list;

4)关闭光标:

它用于释放分配的内存。以下语法用于关闭上面打开的游标。

光标关闭的语法:

Close cursor_name;

PL / SQL显式游标示例

程序员定义了显式游标,以获取对上下文区域的更多控制。它在PL / SQL块的声明部分中定义。它是在SELECT语句上创建的,该语句返回多个行。

让我们以一个示例来演示显式游标的用法。在此示例中,我们使用已创建的CUSTOMERS表。

创建客户表并有记录:

ID NAME AGE ADDRESS SALARY
1 Ramesh 23 Allahabad 20000
2 Suresh 22 Kanpur 22000
3 Mahesh 24 Ghaziabad 24000
4 Chandan 25 Noida 26000
5 Alex 21 Paris 28000
6 Sunita 20 Delhi 30000

创建过程:

执行以下程序以检索客户名称和地址。

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;
/

输出: