来源:蜘蛛抓取(WebSpider)
时间:2016-08-16 19:42
标签:
folder is not open
> PL\SQL用户指南与参考6.2转载其它的OPEN-FOR语句可以使用不同的查询打开同样的游标变量
PL\SQL用户指南与参考6.2转载其它的OPEN-FOR语句可以使用不同的查询打开同样的游标变量
sunray001 & &
发布时间: & &
浏览:78 & &
回复:0 & &
悬赏:0.0希赛币
PL\SQL用户指南与参考6.2
其它的OPEN-FOR语句可以使用不同的查询打开同样的游标变量。在重新打开游标变量之前是不需要关闭它的(但对一个静态游标使用多次OPEN操作时,系统会抛出预定义异常CURSOR_ALREADY_OPEN)。为执行一个不同的查询而重新打开游标变量时,前面的查询结果就会丢失。
一般地,我们可以把游标变量传递给过程,然后由过程负责打开它,如下例,打包过程打开游标变量emp_cv:
emp_data AS
empcurtyp IS
RETURN
emp%ROWTYPE
PROCEDURE
open_emp_cv (emp_cv IN
empcurtyp);END
emp_CREATE
emp_data AS
PROCEDURE
open_emp_cv (emp_cv IN
empcurtyp) IS
emp_cv FOR
SELECT
FROM
open_emp_END
当我们把游标变量声明为一个打开游标变量的子程序的形式参数时,就必须要指定参数模式为IN
OUT模式。那样的话,子程序就可以把一个打开的游标变量返回给调用者。
另外,我们还可以使用独立的过程来打开游标变量。只要简单的在包里定义REF
CURSOR类型,然后在一个独立的过程中引用它就行了。例如,如果我们创建了下面的无体包,我们就能在独立的过程中引用包中所定义的REF CURSOR了:
cv_types AS
genericcurtyp IS
empcurtyp IS
RETURN
emp%ROWTYPE
deptcurtyp IS
RETURN
dept%ROWTYPE
下例中,我们创建一个引用REF CURSOR类型EmpCurTyp的过程,这个类型是在包cv_types中定义的。
open_emp_cv (emp_cv IN
cv_types.empcurtyp) AS
emp_cv FOR
SELECT
FROM
为把数据检索集中化处理,我们可以把一个存储过程中类型兼容的查询进行分组。在下面的例子中,打包过程声明了一个选择器作为它的形势参数。调用时,过程会为选定的查询打开游标变量:
emp_data AS
empcurtyp IS
RETURN
emp%ROWTYPE
PROCEDURE
open_emp_cv (emp_cv IN
empcurtyp, choice INT);END
emp_CREATE
emp_data AS
PROCEDURE
open_emp_cv (emp_cv IN
empcurtyp, choice INT) IS
choice = 1 THEN
OPEN
emp_cv FOR
SELECT
FROM
WHERE
choice = 2 THEN
OPEN
emp_cv FOR
SELECT
FROM
WHERE
sal & 2500;
choice = 3 THEN
OPEN
emp_cv FOR
SELECT
FROM
WHERE
deptno = 20;
为了获取更大的灵活性,我们可以把游标变量和选择器传递给过程,让它执行查询然后返回不同的查询结果。如下例所示:
admin_data AS
gencurtyp IS
PROCEDURE
open_cv (generic_cv IN
gencurtyp, choice INT);END
admin_CREATE
admin_data AS
PROCEDURE
open_cv (generic_cv IN
gencurtyp, choice INT) IS
choice = 1 THEN
OPEN
generic_cv FOR
SELECT
FROM
choice = 2 THEN
OPEN
generic_cv FOR
SELECT
FROM
choice = 3 THEN
OPEN
generic_cv FOR
SELECT
FROM
使用游标变量作为主变量
我们可以在OCI或Pro*C程序这样的PL/SQL主环境中声明游标变量。在使用游标变量之前,我们需要把它作为主变量传递给PL/SQL。在下面的Pro*C例子中,我们把主游标变量和选择器一并传递给PL/SQL块,然后为被选择的查询打开游标变量:
.../* Declare host cursor variable. */
SQL_CURSOR generic_
.../* Initialize host cursor variable. */
ALLOCATE :generic_
.../* Pass host cursor variable and selector to PL/SQL block. */
:choice = 1 THEN
:generic_cv FOR
SELECT
FROM
:choice = 2 THEN
:generic_cv FOR
SELECT
FROM
:choice = 3 THEN
:generic_cv FOR
SELECT
FROM
主游标变量与任何查询的返回类型都兼容,它们就像PL/SQL中的弱类型游标变量一样。
从游标变量中取得数据
FETCH语句能从多行查询的结果集中取得数据,语法如下:
{cursor_variable_name | :host_cursor_variable_name}
{variable_name[, variable_name]... | record_name};
下面的例子中,我们每次都从游标变量emp_cv中取出一条数据放到用户定义的记录emp_rec中:
/* Fetch from cursor variable. */
emp_cv%NOTFOUND; -- exit when last row is fetched
-- process data record
我们可以使用BULK COLLECT子句批量地从游标变量中取得数据放到一个或多个集合中。如下例所示:
empcurtyp IS
RETURN
emp%ROWTYPE
namelist IS
emp.ename%TYPE
sallist IS
emp.sal%TYPE
emp_cv
names
sals BEGIN
emp_cv FOR
SELECT
ename, sal
FROM
当游标变量被打开时,关联查询中的所有变量都会被计算。如果要改变查询中的结果集或要使用变量的最新值,我们就必须重新打开游标变量。不过我们可以为每一个从游标变量中取得数据使用不同的INTO子句。
PL/SQL能保证游标变量的返回类型与FETCH语句中的INTO子句后面的类型相兼容。对于游标变量的关联查询返回的每一个字段,INTO子句后面都必须有一个与之相对应的、类型兼容的域或变量。同样,字段的个数和域的个数也应该相同。否则的话,就会产生错误。如果游标变量是强类型的话,这个错误在编译期就会发生;如果是弱类型,错误会在运行时发生。在运行时,PL/SQL会在第一次取得数据之前抛出预定义异常
ROWTYPE_MISMATCH。所以,如果我们捕获到错误,并使用一个不同的INTO子句再次执行FETCH语句,就不会丢失数据。
如果我们把游标变量声明为从游标变量中取得数据的子程序的形式参数,那么我们必须指定参数模式为IN或IN
OUT模式。但是,如果在子程序中还需要打开游标变量的话,就必须使用IN OUT模式。
如果我们从一个已经关闭了的或是一个未打开的游标变量中选取数据,PL/SQL就会抛出预定义异常INVALID_CURSOR。
关闭游标变量
CLOSE语句会关闭游标变量。如果执行了关闭操作,相关的结果集就不确定了。关闭操作的语法如下:
{cursor_variable_name | :host_cursor_variable_name);
在下面的例子中,当最后一行数据也被处理完毕时,我们就可以关闭游标变量emp_cv:
emp_cv%NOTFOUND;
-- process data record
;/* Close cursor variable. */
当把游标变量作为用于关闭游标变量的子程序的形式参数时,我们必须指定它的参数模式为IN或IN OUT模式。
如果我们从一个已经关闭了的或是一个未打开的游标变量中选取数据,PL/SQL就会抛出预定义异常INVALID_CURSOR。
6、游标变量示例:主从表
思考下面的存储过程,它的作用是搜索图书馆数据库中的图书、期刊和磁带。主表存放标题和类别编号(其中1=书,2=期刊,3=磁带)。三个详细表分别保存特定类别的信息。在调用时,存储过程会按照标题来搜索主表,然后利用主表提供的类别编号到从详细表中检索详细内容。
cv_types AS
libcurtyp IS
FIND_ITEM (title VARCHAR2
lib_cv IN
cv_types.libcurtyp) AS
code BINARY_INTEGER
item_title =
code = 1 THEN
lib_cv FOR
SELECT
FROM
WHERE
book_title =
code = 2 THEN
lib_cv FOR
SELECT
FROM
periodicals
WHERE
periodical_title =
code = 3 THEN
lib_cv FOR
SELECT
FROM
WHERE
tape_title =
FIND_ITEM;
7、游标变量示例:客户端PL/SQL块
一个客户端应用程序可能会使用下面的PL/SQL块来显示检索出来的信息:
lib_cv cv_types.
book_rec books%ROWTYPE
periodical_rec periodicals%ROWTYPE
tape_rec tapes%ROWTYPE
get_title (:title); -- title is a host variable
FIND_ITEM (:title, lib_cv);
display_book (book_rec);EXCEPTION
ROWTYPE_MISMATCH THEN
FETCH
INTO
periodical_
display_periodical (periodical_rec);
EXCEPTION
WHEN
ROWTYPE_MISMATCH THEN
FETCH
INTO
display_tape (tape_rec);
8、游标变量示例:Pro*C程序
下面的Pro*C程序让用户选择一张数据表,然后使用游标变量进行查询,并返回查询结果:
#include &stdio.h&
#include &sqlca.h&
void sql_error();
char temp[32];
EXEC SQL
char * uid = "scott/tiger"
SQL_CURSOR generic_ /* cursor variable */
int table_ /* selector */
struct /* EMP record */
int emp_
char emp_name[11];
char job_title[10];
char hire_date[10];
int dept_
struct /* DEPT record */
int dept_
char dept_name[15];
char location[14];
struct /* BONUS record */
char emp_name[11];
char job_title[10];
} bonus_
EXEC SQL
/* Handle Oracle errors. */
EXEC SQL
SQLERROR DO
sql_error();
/* Connect to Oracle. */
EXEC SQL
/* Initialize cursor variable. */
EXEC SQL
ALLOCATE :generic_
/* Exit loop when done fetching. */
EXEC SQL
for (;;)
printf("\n1 = EMP, 2 = DEPT, 3 = BONUS"
printf("\nEnter table number (0 to quit): "
gets(temp);
table_num = atoi(temp);
if (table_num &= 0)
/* Open cursor variable. */
EXEC SQL
:table_num = 1 THEN
OPEN
:generic_cv FOR
SELECT
FROM
ELSIF
:table_num = 2 THEN
OPEN
:generic_cv FOR
SELECT
FROM
ELSIF
:table_num = 3 THEN
OPEN
:generic_cv FOR
SELECT
FROM
for (;;)
switch (table_num)
case 1: /* Fetch row into EMP record. */
EXEC SQL
:generic_cv INTO
case 2: /* Fetch row into DEPT record. */
EXEC SQL
:generic_cv INTO
case 3: /* Fetch row into BONUS record. */
EXEC SQL
:generic_cv INTO
/* Process data record here. */
/* Close cursor variable. */
EXEC SQL
exit(0);
void sql_error()
/* Handle SQL error here. */
9、游标变量示例:SQL*Plus中操作主变量
主变量就是一个声明在主环境中的变量,它会被传递到一个或多个PL/SQL程序中,在程序中可以跟其他的变量一样使用。在SQL*Plus环境里,可以使用命令VARIABLE来声明主变量。例如,我们可以像下面这样声明一个NUMBER类型的主变量:
VARIABLE return_code NUMBER
SQL*Plus和PL/SQL都能引用主变量,SQL*Plus还可以显示主变量的值。但是,在PL/SQL中引用主变量的时候,我们必须加上冒号(:)前缀,如下例所示:
...BEGIN
:return_code := 0;
credit_check_ok(acct_no) THEN
:return_code := 1;
在SQL*Plus环境里,我们可以使用PRINT命令来显示主变量的值,例如:
& PRINT return_code
RETURN_CODE-----------
SQL*Plus中的REF
CURSOR数据类型可以让我们声明游标变量,这样就可以使用存储子程序返回的查询结果。在下面的脚本中,我们声明了REFCURSOR类型的主变量。我们还可以在SQL*Plus中使用SET
AUTOPRINT ON命令来自动地显示查询结果:
emp_data AS
emprectyp IS
emp_id NUMBER
emp_name VARCHAR2
job_title VARCHAR2
dept_name VARCHAR2
dept_loc VARCHAR2
empcurtyp IS
RETURN
PROCEDURE
get_staff (dept_no IN
, emp_cv IN
empcurtyp);END
emp_data AS
PROCEDURE
get_staff (dept_no IN
, emp_cv IN
empcurtyp) IS
emp_cv FOR
SELECT
empno, ename, job, dname, loc
FROM
WHERE
emp.deptno = dept_no AND
emp.deptno = dept.deptno
ORDER
COLUMN EMPNO HEADING Number
COLUMN ENAME HEADING Name
COLUMN JOB HEADING JobTitle
COLUMN DNAME HEADING Department
COLUMN LOC HEADING LocationSET
AUTOPRINT ON
VARIABLE cv REFCURSOREXECUTE
emp_data.get_staff(20, :cv)
10、在向PL/SQL块传递主游标变量时减少网络负荷
在向PL/SQL传递主游标变量时,我们可以把多个OPEN-FOR语句组合在一起使用,以便减少网络流量。例如,下面的PL/SQL块:
/* anonymous PL/SQL block in host environment */
:emp_cv FOR
SELECT
FROM
:dept_cv FOR
SELECT
FROM
:grade_cv FOR
SELECT
FROM
:pay_cv FOR
SELECT
FROM
:ins_cv FOR
SELECT
FROM
在Oracle Forms中,这种方法可能很有用,比如我们在填充一个多模块窗体的时候。
当我们向PL/SQL块传递一个主游标变量时(游标变量由该块负责打开),游标变量指向的查询工作区在块结束后还是能够被访问的。这就能让我们的OCI或Pro*C程序在普通的游标操作中继续使用这些工作区。下面的例子中,我们在一个块中打开了多个这样的工作区:
SELECT
FROM
SELECT
FROM
SELECT
FROM
SELECT
FROM
SELECT
FROM
赋给c1、c1、c1、c1、c1的游标都可以正常使用。当使用完毕时,只要像下面这样简单的关闭就可以了:
11、避免游标变量的错误
如果在赋值操作中的两个游标变量都是强类型,那么它们必须有着完全相同的数据类型。下面的例子中,虽然游标变量的返回类型相同,但是在赋值操作时也会引起异常,这是因为它们的数据类型不相同:
empcurtyp IS
RETURN
emp%ROWTYPE
tmpcurtyp IS
RETURN
emp%ROWTYPE
PROCEDURE
open_emp_cv (emp_cv IN
empcurtyp, tmp_cv IN
tmpcurtyp) IS
emp_cv := tmp_ -- causes 'wrong type' error
如果其中一个或两个游标变量是弱类型,那它们就没必要类型相同了。
如果我们要对一个没有指向工作区的游标变量进行数据取得、关闭或调用游标属性的操作,PL/SQL就会跑出一个INVALID_CURSOR异常。我们有两种方法可以让游标变量(或参数)指向工作区:
对游标变量使用OPEN-FOR语句。
把一个已经OPEN过的主游标变量赋给PL/SQL游标变量。
下面的例子演示了如何使用这两种方法:
empcurtyp IS
RETURN
emp%ROWTYPE
emp_cv1
emp_cv2
emp_rec emp%ROWTYPE
/* The following assignment is useless because emp_cv1
does not point to a query work area yet. */
emp_cv2 := emp_cv1; -- useless
/* Make emp_cv1 point to a query work area. */
emp_cv1 FOR
SELECT
FROM
/* Use emp_cv1 to fetch first row from emp table. */
/* The following fetch raises an exception because emp_cv2
does not point to a query work area yet. */
emp_ -- raises INVALID_CURSOR
INVALID_CURSOR THEN
/* Make emp_cv1 and emp_cv2 point to same work area. */
emp_cv2 := emp_cv1;
/* Use emp_cv2 to fetch second row from emp table. */
/* Reuse work area for another query. */
emp_cv2 FOR
SELECT
FROM
/* Use emp_cv1 to fetch first row from old_emp table.
The following fetch succeeds because emp_cv1 and
emp_cv2 point to the same query work area. */
emp_ -- succeeds
把游标变量当作参数传递时一定要小心。在运行时,如果实参和形参的返回类型不兼容,PL/SQL就会抛出ROWTYPE_MISMATCH异常。
在下面的Pro*C程序中,我们定义了打包REF
CURSOR类型,并指明返回类型为emp%ROWTYPE。下一步,创建一个引用这个新类型的过程。然后在PL/SQL块内为表dept的查询打开主游标变量。但是,在把打开的游标变量传递给存储过程的时候,由于形参和实参的返回类型不兼容,PL/SQL就抛出了ROWTYPE_MISMATCH异常。
cv_types AS
empcurtyp IS
RETURN
emp%ROWTYPE
open_emp_cv (emp_cv IN
cv_types.empcurtyp) AS
emp_cv FOR
SELECT
FROM
/-- anonymous PL/SQL block in Pro*C program
SELECT
FROM
open_emp_cv (:cv); -- raises ROWTYPE_MISMATCH
12、游标变量的限制
目前,游标变量有以下限制:
不能在包中声明游标变量。例如,下面的声明就是不允许的:
emp_stuff AS
empcurtyp IS
RETURN
emp%ROWTYPE
emp_cv -- not allowed
处于另外一个服务器上的远程子程序不能接受游标变量的值。因此,我们不能使用RPC将游标变量从一个服务器传递到另一个服务器。
如果我们把主游标变量传递到PL/SQL中,就不能在服务器端从这个游标变量中取得数据了,除非打开这个游标变量的操作也是在同一个服务器调用中进行的。
不能简单的用比较操作符来判断两个游标变量是否是相等,不相等或空。
不能为游标变量赋空值。
不能在CREATE TABLE或CREATE VIEW语句中把字段类型指定为REF CURSOR类型。因为数据库字段是不能存放游标变量值的。
不能把REF CURSOR类型作为集合的元素类型,也就是说,索引表,嵌套表和变长数组不能存放游标变量的值。
游标和游标变量不能互相替换。如下例中,不能把适用于游标的FOR循环应用在游标变量上:
EmpCurTyp IS
emp%ROWTYPE
emp_cv EmpCurT
...BEGIN
emp_rec IN
emp_cv LOOP
... -- not allowed
六、使用游标属性
每个显示的游标和游标变量都有四个属性:%FOUND、%ISOPEN、%NOTFOUND和%ROWCOUNT。这些属性都能返回关于数据操作语句执行的有用信息。我们可以在过程化语句中使用游标属性,但不能在SQL语句中使用。
1、显式游标属性一览
每个显式的游标和游标变量都有四个属性:%FOUND、%ISOPEN、%NOFOUND和%ROWCOUNT。我们可以在过程语句中使用这些属性,但不能再SQL语句中使用。
显式游标属性能返回多行查询的信息。当一个显式游标或游标变量被打开时,满足查询条件的行就会被做上标记,最终形成结果集。然后我们就可以就从结果集中取出行数据。
%FOUND属性:行被取出了吗?
在一个游标或游标变量被打开后且在首次取得数据之前,%FOUND会产生NULL值。而此后每取得一行数据,它的值就为TRUE,直到最后一次取得数据失败,它的值变成FALSE。下例中,我们利用%FOUND的值来进行条件判断:
my_ename, my_sal, my_
c1%FOUND THEN
-- fetch succeeded
-- fetch failed, so exit loop
在没有打开游标或游标变量的时候使用%FOUND会引起预定义异常INVALID_CURSOR。
%ISOPEN属性:游标打开了吗?
%ISOPEN在对应的游标或游标变量打开的时候返回TRUE;否则返回FALSE。下例中,我们用%ISOPEN来进行条件判断:
c1%ISOPEN THEN
-- cursor is open
-- cursor is closed, so open it
%NOTFOUND属性:FETCH失败了吗?
%NOTFOUND属性的作用和%FOUND属性正好相反。它在数据取得失败时返回TRUE,成功时返回FALSE。在下面的例子中,当FETCH语句没有取得数据的时候,我们使用%NOTFOUND来退出循环:
my_ename, my_sal, my_
c1%NOTFOUND;
在取数据之前,%NOTFOUND会返回NULL。所以,如果FETCH从来都没有成功执行的话,循环就不会退出。那是因为只有EXIT
WHEN语句中的WHEN子句值为TRUE时,这条语句才能被执行。为了安全起见,我们可以使用下面的EXIT语句进行替换:
c1%NOTFOUND OR
c1%NOTFOUND IS
在没有打开游标或游标变量的时候使用%NOTFOUND会引起预定义异常INVALID_CURSOR。
%ROWCOUNT属性:已经取得了多少条数据?
当游标或游标变量被打开时,%ROWCOUNT值为零。每成功取得一条数据,%ROWCOUNT的值就加一。下例中,我们用%ROWCOUNT来判断取得的数据是否超过十条,然后采取相关的对策:
my_ename, my_
c1%ROWCOUNT & 10 THEN
在没有打开游标或游标变量的时候使用%ROWCOUNT会引起预定义异常INVALID_CURSOR。
下表是执行OPEN、FETCH或CLOSE语句前后对应的游标属性值:
First FETCH
First FETCH
Next FETCH(es)
与数据条数相关
Last FETCH
与数据条数相关
Last FETCH
与数据条数相关
与数据条数相关
如果在游标打开之前或关闭之后引用属性%FOUND、%NOTFOUND或%ROWCOUNT,都会引起INVALID_CURSOR异常。
第一个FETCH之后,如果结果集是空的,%FOUND会产生FALSE,%NOTFOUND会产生TRUE,%ROWCOUNT会产生0。
游标属性的一些实例
假设我们有一个名为data_table的数据表,用它来收集实验室的实验数据,并且我们需要分析实验1的数据。在下面的例子中,我们可以计算出实验结果并把它们放到一个名为temp的数据表中。
num1 data_table.n1%TYPE
; -- Declare variables
num2 data_table.n2%TYPE
; -- having same types as
num3 data_table.n3%TYPE
; -- database columns
RESULT temp.col1%TYPE
SELECT
n1, n2, n3
FROM
data_table
WHERE
exper_num = 1;BEGIN
num1, num2, num3;
c1%NOTFOUND; -- TRUE
when FETCH
finds no more rows
RESULT := num2 / (num1 + num3);
INSERT
VALUES
(RESULT, NULL
在接下来的例子中,我们会检查所有那些包含零件号码为5469的贮藏器,把它们的内容提取出来直到累计到1000个单位:
bin_cur (part_number NUMBER
SELECT
amt_in_bin
FROM
WHERE
part_num = part_number AND
amt_in_bin & 0
ORDER
bin_amt bins.amt_in_bin%TYPE
total_so_far NUMBER
(5) := 0;
amount_needed CONSTANT
(5) := 1000;
bins_looked_at NUMBER
(3) := 0;BEGIN
bin_cur (5469);
total_so_far & amount_needed LOOP
bin_cur%NOTFOUND;
-- if we exit, there's not enough to fill the order
bins_looked_at := bins_looked_at + 1;
total_so_far + bin_amt & amount_needed THEN
UPDATE
SET
amt_in_bin = 0
WHERE
-- take everything in the bin
total_so_far := total_so_far + bin_
-- we finally have enough
UPDATE
SET
amt_in_bin = amt_in_bin - (amount_needed - total_so_far)
WHERE
total_so_far := amount_
VALUES
, bins_looked_at, '&- bins looked at'
2、 隐式游标属性一览
隐式游标属性会返回一些关于INSERT、UPDATE、DELETE和SELECT
INTO语句的执行信息。这些属性值总是与最近一次执行的语句相关。在Oracle打开SQL游标之前,隐式游标的所有属性都是NULL。
要注意SQL游标还有另外一个专门为FORALL语句设计的%BULK_ROWCOUNT属性。
隐式游标属性和显式游标相同,也有%FOUND、%ISOPEN、%NOTFOUND和%ROWCOUNT,并且这些属性的用法也和显式游标的类似,这里就不再详细说明。由于Oracle在执行完语句后会自动关闭SQL游标,所以SQL游标的%ISOPEN属性值总是FALSE。
隐式游标属性的使用准则
隐式游标的属性值总是与最后一次执行的语句相关,无论这个语句处于哪个作用域。所以,如果我们想把一个属性值保存起来以便以后使用,就要立即把它赋给一个布尔变量。下面的例子中依赖于IF语句的条件是很危险的,因为过程check_status可能会改变属性%NOTFOUND的值:
quantity = quantity - 1 WHERE
partno = part_
check_status(part_id); -- procedure call
%NOTFOUND THEN
-- dangerous!
我们可以像下面这样改善代码:
quantity = quantity - 1 WHERE
partno = part_
sql_notfound := SQL
%NOTFOUND; -- assign value to Boolean variable
check_status(part_id);
sql_notfound THEN
如果SELECT INTO没有返回结果,PL/SQL就会抛出预定义异常NO_DATA_FOUND。如下例:
my_sal FROM
empno = my_
-- might raise NO_DATA_FOUND
%NOTFOUND THEN
-- condition tested only when false
... -- this action is never taken
上面的检查是没有作用的,因为IF语句只在%NOTFOUND值是假的情况下才能进行检查。当PL/SQL抛出NO_DATA_FOUND异常,正常的执行就会终止,控制权被交给异常处理部分。
但一个调用聚合函数的SELECT
INTO语句从来不会抛出异常NO_DATA_FOUND,因为聚合函数总会返回一个值或空。在这种情况下,%NOTFOUND就会产生FALSE,如下例:
(sal) INTO
my_sal FROM
deptno = my_
-- never raises NO_DATA_FOUND
%NOTFOUND THEN
-- always tested but never true
... -- this action is never taken
;EXCEPTION
NO_DATA_FOUND THEN
... -- never invoked
七、使用游标表达式
一个游标表达式能返回一个嵌套游标。结果集中的每一行跟平常一样,每个字段都包含一些值,其中的一些包含的是嵌套游标。因此,一个独立的查询就能返回从多个数据表间检索出来的相关值。我们可以用嵌套循环来处理结果集,然后再处理每一行中的嵌套游标。
PL/SQL支持把游标表达式作为游标声明、REF CURSOR声明和游标变量的一部分的查询。我们还可以在动态游标查询中使用游标表达式。语法如下:
( subquery )
在从父级游标取得数据时,嵌套游标就会被隐式地打开。嵌套游标只有在下面的情况下才会被关闭:
嵌套游标被用户显式地关闭
父级游标被重新执行
父级游标被关闭
父级游标被取消
在从嵌套游标的一个父级游标中取数据时发生错误。嵌套游标会被作为清理内容的一部分而被关闭
1、游标表达式的约束
不能在隐式游标中使用游标表达式
游标表达式只能出现在:
非子查询的SELECT语句中,并且这条语句不能是游标表达式本身的子查询
作为table函数的参数,出现在SELECT语句的FROM子句中
游标表达式只能出现在查询说明的SELECT列表中
游标表达式不能出现在视图声明中
不能对游标表达式进行BIND和EXECUTE操作
2、游标表达式的示例
下例中,我们要用一个游标取出某个指定ID的地区中所有的部门。在我们取得每一个部门名称的过程中,我们也会从另一张表取出该部门雇员的详细信息。
REPLACE PROCEDURE
emp_report (p_locid NUMBER
refcursor IS
-- The query returns only 2 columns, but the second column is
-- a cursor that lets us traverse a set of related information.
SELECT
CURSOR
d.department_name,
CURSOR
e.last_name
FROM
employees e
WHERE
e.department_id = d.department_id
) AS
FROM
departments d
WHERE
l.location_id = d.location_id
) dname
FROM
locations l
WHERE
l.location_id = p_
loccur
deptcur
empcur
v_city locations.city%TYPE
v_dname departments.department_name%TYPE
v_ename employees.last_name%TYPE
c1%NOTFOUND;
-- We can access the column C1.city, then process the results of
-- the nested cursor.
FETCH
INTO
v_dname, -- No need to open
EXIT
loccur%NOTFOUND;
LOOP
FETCH
INTO
v_ -- No need to open
EXIT
deptcur%NOTFOUND;
DBMS_OUTPUT.put_line (v_city || ' '
|| v_dname || ' '
|| v_ename);
本问题标题:
本问题地址:
温馨提示:本问题已经关闭,不能解答。
暂无合适的专家
&&&&&&&&&&&&&&&
希赛网 版权所有 & &&