在本章中,我们将讨论和学习pl/sql
中的游标。 oracle创建一个称为上下文区域的内存区域,用于处理sql语句,它包含处理该语句所需的所有信息; 例如,处理的行数等。
游标是指向此上下文区域的指针。pl/sql
通过游标控制上下文区域,游标保存sql语句返回的行(一个或多个)。 游标所在的行集称为活动集。
可以命名一个游标,以便在程序中引用它来获取和处理sql语句返回的行,一次处理一个(行)。pl/sql中有两种类型的游标 -
当执行sql语句时,如果语句没有显式游标,则oracle会自动创建隐式游标。程序员无法控制隐式游标及其信息。
每当发出dml语句(insert
,update
和delete
)时,隐式游标与此语句相关联。 对于insert
操作,游标保存需要插入的数据。对于update
和delete
操作,游标标识将受到影响的行。
在pl/sql中,可以将最近的隐式游标引用为sql游标,它始终具有%found
,%isopen
,%notfound
和%rowcount
等属性。 sql游标具有额外的属性%bulk_rowcount
和%bulk_exceptions
,旨在与forall
语句一起使用。下表提供了游标中最常用属性的描述 -
编号 | 属性 | 描述 |
---|---|---|
1 | %found |
如果insert ,update 或delete 语句影响一行或多行,或老兄select into 语句返回一行或多行,则返回true ,否则返回false 。 |
2 | %notfound |
与%found 的逻辑相反。 如果insert,update或delete语句没有影响任何行,或select into语句未返回任何行,则返回true。 否则返回false。 |
3 | %isopen |
由于oracle在执行关联的sql语句后会自动关闭sql游标,因此总是为隐式游标返回false 。 |
4 | %rowcount |
返回受insert ,update 或delete 语句,或者受select into 语句影响的行数。 |
任何sql游标属性将被访问为sql%attribute_name
,如下例所示。
这里将使用在前几章中创建和使用的customers
表,表结构和数据参考: http://www.h3.com/plsql/plsql_variable_types.html
create table customers(
id int not null,
name varchar (20) not null,
age int not null,
address char (25),
salary decimal (18, 2),
primary key (id)
);
-- 插入数据
insert into customers (id,name,age,address,salary)
values (1, 'ramesh', 32, 'ahmedabad', 2000.00 );
insert into customers (id,name,age,address,salary)
values (2, 'khilan', 25, 'delhi', 1500.00 );
insert into customers (id,name,age,address,salary)
values (3, 'kaushik', 23, 'kota', 2000.00 );
insert into customers (id,name,age,address,salary)
values (4, 'chaitali', 25, 'mumbai', 6500.00 );
insert into customers (id,name,age,address,salary)
values (5, 'hardik', 27, 'bhopal', 8500.00 );
insert into customers (id,name,age,address,salary)
values (6, 'komal', 22, 'mp', 4500.00 );
以下程序将表中每个客户的工资增加500
,并使用sql%rowcount
属性来确定受影响的行数 -
set serveroutput on size 99999;
declare
total_rows number(2);
begin
update customers
set salary = salary + 500;
if sql%notfound then
dbms_output.put_line('没有找到客户信息~');
elsif sql%found then
total_rows := sql%rowcount;
dbms_output.put_line('一共有:' || total_rows || ' 个客户的工资被更新! ');
end if;
end;
/
执行上面示例代码,得到以下结果 -
如果查询了客户表中的记录,会发现工资已更新(增加了500) -
sql> select id,name,salary from customers;
id name salary
---------- -------------------- ----------
1 ramesh 2500
2 khilan 2000
3 kaushik 2500
4 chaitali 7000
5 hardik 9000
6 komal 5000
显式游标是用于获得对上下文区域的更多控制的程序员定义的游标。应在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;
以下是一个完整的例子来说明显式游标的概念。
set serveroutput on size 99999;
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;
/
执行上面示例代码,得到以下结果 -