- 浏览: 251062 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
Orc3Ming:
哦,脚本的解释路径,不是注释。
RHEL6.4更改为CentOS6.4的yum源 -
Orc3Ming:
将第一行 #!/usr/bin/python 修改为 #!/u ...
RHEL6.4更改为CentOS6.4的yum源 -
anniecharlotte:
请问:如果登录某个节点
执行nodetool ring查看集群 ...
Cassandra集群 -
Q_Qkings8:
给了我好的提示,已经成功的解决了问题
Eclipse Debug Source not found for -
kevin.wang:
feijin1981 写道我也有同样的问题,但是Window ...
Eclipse Debug Source not found for
REF CURSOR 小结
利用REF CURSOR,可以在程序间传递结果集(一个程序里打开游标变量,在另外的程序里处理数据)。
也可以利用REF CURSOR实现BULK SQL,提高SQL性能。
REF CURSOR分两种,Strong REF CURSOR 和 Weak REF CURSOR。
Strong REF CURSOR:指定retrun type,CURSOR变量的类型必须和return type一致。
DECLARE
TYPE strongcurtyp IS REF CURSOR RETURN emp%ROWTYPE;
emp_cv strongcurtyp;
Weak REF CURSOR:不指定return type,能和任何类型的CURSOR变量匹配。
DECLARE
TYPE weakcurtyp IS REF CURSOR;
weak_cv weakcurtyp;
any_cv SYS_REFCURSOR; --使用SYS_REFCURSOR可以使变量any_cv跟任何weak REF CURSOR类型匹配。
使用Strong REF CURSOR例子
CREATE OR REPLACE PACKAGE emp_data AS
TYPE empcurtyp IS REF CURSOR RETURN emp%rowtype; --定义TYPE as Strong REF CURSOR
PROCEDURE open_emp_cv(emp_cv IN OUT empcurtyp, choice INT); --根据不同的choice选择不同的CURSOR
PROCEDURE retrieve_data(choice INT); --通过调用procedure open_emp_cv,返回指定的结果集。
END emp_data;
=============================================
CREATE OR REPLACE PACKAGE BODY emp_data AS
--procedure open_emp_cv-----------------------------
PROCEDURE open_emp_cv(emp_cv IN OUT empcurtyp, choice INT) IS --emp_cv作为传入/传出的CURSOR PARAMETER
BEGIN
IF choice = 1 THEN
OPEN emp_cv FOR
SELECT * FROM emp WHERE empno < 7800;
ELSIF choice = 2 THEN
OPEN emp_cv FOR
SELECT * FROM emp WHERE SAL < 1000;
ELSIF choice = 3 THEN
OPEN emp_cv FOR
SELECT * FROM emp WHERE ename like 'J%';
END IF;
END;
--procedure retrieve_data----------------------------------
PROCEDURE retrieve_data(choice INT) IS
return_cv empcurtyp; --定义传入open_emp_cv的CURSOR变量
return_row emp%ROWTYPE;
invalid_choice EXCEPTION;
BEGIN
open_emp_cv(return_cv, choice); --调用 procedure OPEN_EMP_CV
IF choice = 1 THEN
DBMS_OUTPUT.PUT_LINE('EMPLOYEES with empno less than 7800');
ELSIF choice = 2 THEN
DBMS_OUTPUT.PUT_LINE('EMPLOYEES with salary less than 1000');
ELSIF choice = 3 THEN
DBMS_OUTPUT.PUT_LINE('EMPLOYEES with name starts with ''J''');
ELSE
RAISE invalid_choice;
END IF;
LOOP
FETCH return_cv
INTO return_row;
EXIT WHEN return_cv%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(return_row.empno || '--' || return_row.ename || '--' ||
return_row.sal);
END LOOP;
EXCEPTION
WHEN invalid_choice THEN
DBMS_OUTPUT.PUT_LINE('The CHOICE should be in one of (1,2,3)!');
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Errors in procedure RETRIEVE_DATA!');
END;
END emp_data;
================================
执行:
SQL> EXEC emp_data.retrieve_data(1);
EMPLOYEES with empno less than 7800
7369--SMITH--800
7499--ALLEN--1600
7521--WARD--1250
7566--JONES--2975
7654--MARTIN--1250
7698--BLAKE--2850
7782--CLARK--2450
7788--SCOTT--3000
PL/SQL procedure successfully completed
SQL> EXEC emp_data.retrieve_data(2);
EMPLOYEES with salary less than 1000
7369--SMITH--800
7900--JAMES--950
PL/SQL procedure successfully completed
SQL> EXEC emp_data.retrieve_data(3);
EMPLOYEES with name starts with 'J'
7566--JONES--2975
7900--JAMES--950
PL/SQL procedure successfully completed
SQL> EXEC emp_data.retrieve_data(34);
The CHOICE should be in one of (1,2,3)!
PL/SQL procedure successfully completed
使用Weak REF CURSOR例子
--procedure open_cv---------------------------------------
create or replace procedure open_cv(choice IN INT,
return_cv OUT SYS_REFCURSOR) is
--参数return_cv为weak REF CURSOR,利用SYS_CURSOR来定义
begin
if choice = 1 then
open return_cv for 'select * from emp';
elsif choice = 2 then
open return_cv for 'select * from dept';
end if;
end open_cv;
--procedure retrieve_data------------------------------------
create or replace procedure retrieve_data(choice IN INT) is
emp_rec emp%rowtype;
dept_rec dept%rowtype;
return_cv SYS_REFCURSOR;
invalid_choice exception;
begin
if choice=1 then
dbms_output.put_line('employee information');
open_cv(1,return_cv); --调用procedure open_cv;
loop
fetch return_cv into emp_rec;
exit when return_cv%notfound;
dbms_output.put_line(emp_rec.empno||'-'||emp_rec.ename||'-'||emp_rec.sal);
end loop;
elsif choice=2 then
dbms_output.put_line('department information');
open_cv(2,return_cv);
loop
fetch return_cv into dept_rec;
exit when return_cv%notfound;
dbms_output.put_line(dept_rec.deptno||'-'||dept_rec.dname||'-'||dept_rec.loc);
end loop;
else
raise invalid_choice;
end if;
exception
when invalid_choice then
dbms_output.put_line('The CHOICE should be one of 1 and 2!');
when others then
dbms_output.put_line('Errors in procedure retrieve_data');
end retrieve_data;
-----------------------------------------------------------------
执行:
SQL> exec retrieve_data(1);
employee information
7369-SMITH-800
7499-ALLEN-1600
7521-WARD-1250
7566-JONES-2975
7654-MARTIN-1250
7698-BLAKE-2850
......
PL/SQL procedure successfully completed
SQL> exec retrieve_data(2);
department information
10-ACCOUNTING-NEW YORK
20-RESEARCH-DALLAS
30-SALES-CHICAGO
40-OPERATIONS-BOSTON
PL/SQL procedure successfully completed
用REF CURSOR实现BULK功能
1. To speed up INSERT, UPDATE, and DELETE statements, enclose the SQL statement within a PL/SQL FORALL statement instead of a loop construct.
2. To speed up SELECT statements, include the BULK COLLECT INTO clause in the SELECT statement instead of using INTO.
SQL> create table tab2 as select empno ID, ename NAME, sal SALARY from emp where 1=2;
Table created
-------------------------------------------------------
create or replace procedure REF_BULK is
type empcurtyp is ref cursor;
type idlist is table of emp.empno%type;
type namelist is table of emp.ename%type;
type sallist is table of emp.sal%type;
emp_cv empcurtyp;
ids idlist;
names namelist;
sals sallist;
row_cnt number;
begin
open emp_cv for
select empno, ename, sal from emp;
fetch emp_cv BULK COLLECT
INTO ids, names, sals; --BULK COLLECT INTO instead of INTO
close emp_cv;
for i in ids.first .. ids.last loop
dbms_output.put_line('id=' || ids(i) || ' name=' || names(i) ||
' salary=' || sals(i));
end loop;
forall i in ids.first .. ids.last --FORALL instead of FOR ...LOOP
insert into tab2 values (ids(i), names(i), sals(i));
commit;
select count(*) into row_cnt from tab2;
dbms_output.put_line('-----------------------------------');
dbms_output.put_line('The row number of tab2 is ' || row_cnt);
end REF_BULK;
------------------------------------------------------------
执行:
SQL> exec ref_bulk;
id=7369 name=SMITH salary=800
id=7499 name=ALLEN salary=1600
id=7521 name=WARD salary=1250
id=7566 name=JONES salary=2975
id=7654 name=MARTIN salary=1250
id=7698 name=BLAKE salary=2850
id=7782 name=CLARK salary=2450
id=7788 name=SCOTT salary=3000
id=7839 name=KING salary=5000
id=7844 name=TURNER salary=1500
id=7876 name=ADAMS salary=1100
id=7900 name=JAMES salary=950
id=7902 name=FORD salary=3000
id=7934 name=MILLER salary=1300
-----------------------------------
The row number of tab2 is 14
PL/SQL procedure successfully completed
利用REF CURSOR,可以在程序间传递结果集(一个程序里打开游标变量,在另外的程序里处理数据)。
也可以利用REF CURSOR实现BULK SQL,提高SQL性能。
REF CURSOR分两种,Strong REF CURSOR 和 Weak REF CURSOR。
Strong REF CURSOR:指定retrun type,CURSOR变量的类型必须和return type一致。
DECLARE
TYPE strongcurtyp IS REF CURSOR RETURN emp%ROWTYPE;
emp_cv strongcurtyp;
Weak REF CURSOR:不指定return type,能和任何类型的CURSOR变量匹配。
DECLARE
TYPE weakcurtyp IS REF CURSOR;
weak_cv weakcurtyp;
any_cv SYS_REFCURSOR; --使用SYS_REFCURSOR可以使变量any_cv跟任何weak REF CURSOR类型匹配。
使用Strong REF CURSOR例子
CREATE OR REPLACE PACKAGE emp_data AS
TYPE empcurtyp IS REF CURSOR RETURN emp%rowtype; --定义TYPE as Strong REF CURSOR
PROCEDURE open_emp_cv(emp_cv IN OUT empcurtyp, choice INT); --根据不同的choice选择不同的CURSOR
PROCEDURE retrieve_data(choice INT); --通过调用procedure open_emp_cv,返回指定的结果集。
END emp_data;
=============================================
CREATE OR REPLACE PACKAGE BODY emp_data AS
--procedure open_emp_cv-----------------------------
PROCEDURE open_emp_cv(emp_cv IN OUT empcurtyp, choice INT) IS --emp_cv作为传入/传出的CURSOR PARAMETER
BEGIN
IF choice = 1 THEN
OPEN emp_cv FOR
SELECT * FROM emp WHERE empno < 7800;
ELSIF choice = 2 THEN
OPEN emp_cv FOR
SELECT * FROM emp WHERE SAL < 1000;
ELSIF choice = 3 THEN
OPEN emp_cv FOR
SELECT * FROM emp WHERE ename like 'J%';
END IF;
END;
--procedure retrieve_data----------------------------------
PROCEDURE retrieve_data(choice INT) IS
return_cv empcurtyp; --定义传入open_emp_cv的CURSOR变量
return_row emp%ROWTYPE;
invalid_choice EXCEPTION;
BEGIN
open_emp_cv(return_cv, choice); --调用 procedure OPEN_EMP_CV
IF choice = 1 THEN
DBMS_OUTPUT.PUT_LINE('EMPLOYEES with empno less than 7800');
ELSIF choice = 2 THEN
DBMS_OUTPUT.PUT_LINE('EMPLOYEES with salary less than 1000');
ELSIF choice = 3 THEN
DBMS_OUTPUT.PUT_LINE('EMPLOYEES with name starts with ''J''');
ELSE
RAISE invalid_choice;
END IF;
LOOP
FETCH return_cv
INTO return_row;
EXIT WHEN return_cv%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(return_row.empno || '--' || return_row.ename || '--' ||
return_row.sal);
END LOOP;
EXCEPTION
WHEN invalid_choice THEN
DBMS_OUTPUT.PUT_LINE('The CHOICE should be in one of (1,2,3)!');
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Errors in procedure RETRIEVE_DATA!');
END;
END emp_data;
================================
执行:
SQL> EXEC emp_data.retrieve_data(1);
EMPLOYEES with empno less than 7800
7369--SMITH--800
7499--ALLEN--1600
7521--WARD--1250
7566--JONES--2975
7654--MARTIN--1250
7698--BLAKE--2850
7782--CLARK--2450
7788--SCOTT--3000
PL/SQL procedure successfully completed
SQL> EXEC emp_data.retrieve_data(2);
EMPLOYEES with salary less than 1000
7369--SMITH--800
7900--JAMES--950
PL/SQL procedure successfully completed
SQL> EXEC emp_data.retrieve_data(3);
EMPLOYEES with name starts with 'J'
7566--JONES--2975
7900--JAMES--950
PL/SQL procedure successfully completed
SQL> EXEC emp_data.retrieve_data(34);
The CHOICE should be in one of (1,2,3)!
PL/SQL procedure successfully completed
使用Weak REF CURSOR例子
--procedure open_cv---------------------------------------
create or replace procedure open_cv(choice IN INT,
return_cv OUT SYS_REFCURSOR) is
--参数return_cv为weak REF CURSOR,利用SYS_CURSOR来定义
begin
if choice = 1 then
open return_cv for 'select * from emp';
elsif choice = 2 then
open return_cv for 'select * from dept';
end if;
end open_cv;
--procedure retrieve_data------------------------------------
create or replace procedure retrieve_data(choice IN INT) is
emp_rec emp%rowtype;
dept_rec dept%rowtype;
return_cv SYS_REFCURSOR;
invalid_choice exception;
begin
if choice=1 then
dbms_output.put_line('employee information');
open_cv(1,return_cv); --调用procedure open_cv;
loop
fetch return_cv into emp_rec;
exit when return_cv%notfound;
dbms_output.put_line(emp_rec.empno||'-'||emp_rec.ename||'-'||emp_rec.sal);
end loop;
elsif choice=2 then
dbms_output.put_line('department information');
open_cv(2,return_cv);
loop
fetch return_cv into dept_rec;
exit when return_cv%notfound;
dbms_output.put_line(dept_rec.deptno||'-'||dept_rec.dname||'-'||dept_rec.loc);
end loop;
else
raise invalid_choice;
end if;
exception
when invalid_choice then
dbms_output.put_line('The CHOICE should be one of 1 and 2!');
when others then
dbms_output.put_line('Errors in procedure retrieve_data');
end retrieve_data;
-----------------------------------------------------------------
执行:
SQL> exec retrieve_data(1);
employee information
7369-SMITH-800
7499-ALLEN-1600
7521-WARD-1250
7566-JONES-2975
7654-MARTIN-1250
7698-BLAKE-2850
......
PL/SQL procedure successfully completed
SQL> exec retrieve_data(2);
department information
10-ACCOUNTING-NEW YORK
20-RESEARCH-DALLAS
30-SALES-CHICAGO
40-OPERATIONS-BOSTON
PL/SQL procedure successfully completed
用REF CURSOR实现BULK功能
1. To speed up INSERT, UPDATE, and DELETE statements, enclose the SQL statement within a PL/SQL FORALL statement instead of a loop construct.
2. To speed up SELECT statements, include the BULK COLLECT INTO clause in the SELECT statement instead of using INTO.
SQL> create table tab2 as select empno ID, ename NAME, sal SALARY from emp where 1=2;
Table created
-------------------------------------------------------
create or replace procedure REF_BULK is
type empcurtyp is ref cursor;
type idlist is table of emp.empno%type;
type namelist is table of emp.ename%type;
type sallist is table of emp.sal%type;
emp_cv empcurtyp;
ids idlist;
names namelist;
sals sallist;
row_cnt number;
begin
open emp_cv for
select empno, ename, sal from emp;
fetch emp_cv BULK COLLECT
INTO ids, names, sals; --BULK COLLECT INTO instead of INTO
close emp_cv;
for i in ids.first .. ids.last loop
dbms_output.put_line('id=' || ids(i) || ' name=' || names(i) ||
' salary=' || sals(i));
end loop;
forall i in ids.first .. ids.last --FORALL instead of FOR ...LOOP
insert into tab2 values (ids(i), names(i), sals(i));
commit;
select count(*) into row_cnt from tab2;
dbms_output.put_line('-----------------------------------');
dbms_output.put_line('The row number of tab2 is ' || row_cnt);
end REF_BULK;
------------------------------------------------------------
执行:
SQL> exec ref_bulk;
id=7369 name=SMITH salary=800
id=7499 name=ALLEN salary=1600
id=7521 name=WARD salary=1250
id=7566 name=JONES salary=2975
id=7654 name=MARTIN salary=1250
id=7698 name=BLAKE salary=2850
id=7782 name=CLARK salary=2450
id=7788 name=SCOTT salary=3000
id=7839 name=KING salary=5000
id=7844 name=TURNER salary=1500
id=7876 name=ADAMS salary=1100
id=7900 name=JAMES salary=950
id=7902 name=FORD salary=3000
id=7934 name=MILLER salary=1300
-----------------------------------
The row number of tab2 is 14
PL/SQL procedure successfully completed
发表评论
-
connect by prior
2012-01-29 14:41 747http://www.blogjava.net/freeman ... -
Oracle 解锁
2011-08-22 11:32 836在for update 查询时,线程被阻塞 查询阻塞线程: ... -
exists与in
2011-07-27 20:53 10121. exists: 不缓存exists() ... -
outer join , inner join , cross join
2010-11-30 13:18 888select * from table1; ID NAME 1 ... -
查看Oracle表空间 tablespace
2010-10-29 09:32 11411. 查看所有表空间大小 SQL> select ta ... -
Oracle--create user& tablespace
2010-10-29 09:22 2608-建立表空间(oracle中的tablespace(表空间)就 ... -
win7下安装Oracle10g
2010-10-03 01:01 1084解决方案: 步骤一:在解压出的oracle文件夹中搜 ... -
Oracle 关于密码及密码文件
2010-09-29 10:49 1618以安装Oracle的用户进入系统: 忘记密码: 1.在命令行下 ... -
修改Oracle端口
2010-09-02 19:20 1401<script>function StorePag ... -
关于Oracle 10g 默认用户、密码及登录问题
2010-09-02 19:02 1960Oracle 10g 默认用户、密码 参见http://sap ... -
Oracle 之 Sequence
2010-08-13 09:01 8231、Create Sequence 你首先要有CREATE ... -
存储过程中 调用 Java
2010-08-12 11:39 894一、如何创建java存储过程? 通常有三种方法来创建java存 ... -
Java 调用Oracle 存储过程
2010-08-12 10:45 16311、存储过程是指保存在 ... -
Java 调用Oracle 函数
2010-08-12 10:26 1544oracle的存储过程和函数区别 1、都可以使用out参数返 ... -
Merge Into
2010-08-12 10:22 1366用途 merge 命令可以用 ... -
Returnning Into 总结
2010-08-12 09:45 1095ORACLE的DML语句中可以指定RETURNING语句。使用 ... -
Pro * C 的使用(三)
2010-08-11 18:05 1107(7) 动态定义语句 SQL语句分动态定义语句和静态 ... -
Pro * C 的使用(二)
2010-08-11 18:02 13632.应用程序体 在Pro*C ... -
Pro * C 的使用(一)
2010-08-11 17:59 1177一 Pro*C 程序概述: ... -
fetch bulk collect into 批量效率的读取游标数据
2010-08-11 16:14 1212通常我们获取游标数据是用 fetch some_cursor ...
相关推荐
尽管如此,从REF CURSOR到ResultSet的逆向映射仍然不被支持,这意味着在当前版本中,你无法将REF CURSOR作为IN或IN OUT参数传递给Java存储过程。 为了从Java存储过程返回一个ResultSet作为REF CURSOR,需要特别处理...
在Oracle数据库环境中,合并多个`sys_refcursor`(也称为游标)的需求常常出现在复杂的业务逻辑中,尤其是在需要重复调用相同逻辑的存储过程时。本文将详细介绍如何通过序列化和XML处理来实现这一功能。 首先,让...
ResultSet rs = (ResultSet) refCursor.getBaseCursor(); // 遍历ResultSet while (rs.next()) { System.out.println(rs.getString(1)); } ``` ### 四、总结 通过上述步骤,我们可以看到在JDBC程序中使用REF ...
例如,过程定义为`PROCEDURE get_data(p_rc OUT SYS_REFCURSOR);`,然后在调用时捕获返回的游标。 - **记录类型**: 另一种方法是定义一个记录类型,该类型与REF CURSOR返回的列结构匹配,然后返回一个包含此记录...
要使过程返回数据集,关键在于使用`OUT`类型的参数,并且该参数应为`sys_refCursor`系统引用游标类型。这样,过程可以在PL/SQL程序中将数据集作为输出传递给调用者。例如,在提供的示例中,`add_sal`过程接受一个...
v_refcursor SYS_REFCURSOR; BEGIN v_query := 'SELECT * FROM employees WHERE department_id = ' || dept_id; OPEN v_refcursor FOR v_query; RETURN v_refcursor; END; ``` 在这个函数中,我们动态构造了SQL...
在 Oracle 的 PL/SQL 环境中,Refcursor 是一种特殊的游标类型,它可以作为函数的结果返回或存储过程的输出参数来传递结果集。为了能够使用 Refcursor,首先需要定义一个新的类型来表示它: - **弱类型派生**:这种...
2. Ref Cursor类型:Ref Cursor类型是一种 Oracle 数据类型,用于表示游标或结果集。 3. Java调用Oracle存储过程:Java程序可以通过JDBC来调用Oracle存储过程,获取结果集。 4. Type类型:Type类型是Oracle中的一种...
首先,我们需要创建一个Oracle存储过程,该过程定义了一个名为CURSOR_RESULT的REF CURSOR类型。在提供的示例中,我们有一个名为TEST的包,包含一个名为GET_CURSOR_RESULT的存储过程。该过程接受四个参数:P_...
使用此程序包,您现在可以运行返回RefCursor的存储过程,或使用数组绑定计数来执行带有参数数组的sql语句。 受支持的Oracle特定属性 OracleParameter(托管和非托管) OracleDbType枚举(托管提供者使用的所有成员...
当存储过程被调用时,它可以在内部执行SQL查询,并将结果存储在一个Ref Cursor中,然后将这个Ref Cursor作为输出参数返回给调用者。 #### 三、创建存储过程返回结果集 ##### 1. 过程返回记录集 下面是一个简单的...
REF CURSOR类型的声明通常放在包规范(PACKAGE SPECIFICATION)中,然后在包主体(PACKAGE BODY)中定义具体的过程来打开和处理这个游标。以下是一个例子: ```sql CREATE OR REPLACE PACKAGE pkg_test AS TYPE ...
OPEN v_refCursor FOR 'SELECT ename, sal FROM emp'; LOOP FETCH v_refCursor INTO v_ename, v_salary; EXIT WHEN v_refCursor%NOTFOUND; -- 处理数据... END LOOP; CLOSE v_refCursor; END; ``` 总结来说...
3. **REF CURSOR**:这是一种动态游标,允许返回任意查询的结果集。它常用于存储过程和函数中,将结果集作为输出参数传递。 4. **命名游标**:通过为显式游标指定名称,可以在PL/SQL块的不同部分引用同一个游标,...
这里的关键技术是使用REFCURSOR(引用游标),它是一种特殊类型的游标,可以作为存储过程的输出参数,使得一个存储过程能够返回多个结果集。 ### Oracle返回多个结果集 #### 一、基本概念 在Oracle数据库中,通常...
v_refcur SYS_REFCURSOR; BEGIN OPEN v_refcur FOR SELECT * FROM table1; LOOP FETCH v_refcur INTO v_rec; EXIT WHEN v_refcur%NOTFOUND; -- 处理记录 END LOOP; CLOSE v_refcur; END; ``` 静态SQL和动态...
type qdy_cursor is ref cursor; end qdy_package; create or replace procedure qdy_pro2(p_cursor out qdy_package.qdy_cursor) is begin open p_cursor for select * from emp; end; --函数 create function ...
CREATE OR REPLACE FUNCTION get_data (OUT ref_cur SYS_REFCURSOR) AS BEGIN OPEN ref_cur FOR SELECT * FROM table_name; END; ``` - **使用Ref Cursor**: ```sql DECLARE ref_cur SYS_REFCURSOR; ...
TYPE c_s IS REFCURSOR RETURN table%ROWTYPE; TYPE c_s2 IS REFCURSOR; var_cs c_s; BEGIN OPEN c_s FOR SELECT * FROM admin; CLOSE c_s; END; ``` 这段代码展示了如何声明并使用一个返回特定表行类型的REF ...