日期:2014-05-16  浏览次数:20653 次

能否通过数据库链传播游标

在处理页面的查询时,经常使用的一种方法是,在数据库服务器上的存储过程打开游标,然后将游标直接返回给页面处理的程序。

今天同事在处理游标的时候提出一个问题:是否可以将游标传给另一台数据库服务器的存储过程呢?

?

首先看个最简单的例子,用游标将结果集返回给SQLPLUS客户端:

SQL> CONN TEST/TEST@TEST2已连接。
SQL> CREATE TABLE TEST AS SELECT ROWNUM ID, TABLE_NAME NAME FROM ALL_TABLES WHERE OWNER = 'SYSTEM';

表已创建。

SQL> CREATE OR REPLACE PACKAGE PKG_TEST AS
2 TYPE C_CURSOR IS REF CURSOR;
3 END;
4 /

程序包已创建。

SQL> CREATE OR REPLACE PROCEDURE P_TEST (P_CURSOR OUT PKG_TEST.C_CURSOR) AS
2 BEGIN
3 OPEN P_CURSOR FOR SELECT * FROM TEST;
4 END;
5 /

过程已创建。

SQL> VAR CUR REFCURSOR
SQL> EXEC P_TEST(:CUR)

PL/SQL 过程已成功完成。

SQL> PRINT :CUR

ID NAME
---------- ------------------------------
1 DEF$_TEMP$LOB
2 HELP
3 MVIEW$_ADV_INDEX
4 MVIEW$_ADV_OWB
5 MVIEW$_ADV_PARTITION

下面尝试在其他数据库中接收这个游标变量:

SQL> CONN YANGTK/YANGTK已连接。
SQL> CREATE DATABASE LINK TEST2 CONNECT TO TEST IDENTIFIED BY TEST USING 'TEST2';

数据库链接已创建。

SQL> VAR CUR2 REFCURSOR
SQL> EXEC P_TEST@TEST2(:CUR2)

PL/SQL 过程已成功完成。

SQL> PRINT :CUR2
ERROR:
ORA-24338:
未执行语句句柄

?

未选定行

对于这种希望从远端数据库得到游标只能通过下面的变相的方式获得:

SQL> CREATE OR REPLACE PACKAGE PKG_TEST AS
2 TYPE C_CURSOR IS REF CURSOR;
3 END;
4 /

程序包已创建。

SQL> CREATE OR REPLACE PROCEDURE P_TEST (P_CURSOR OUT PKG_TEST.C_CURSOR) AS
2 BEGIN
3 OPEN P_CURSOR FOR SELECT * FROM TEST@TEST2;
4 END;
5 /

过程已创建。

SQL> EXEC P_TEST(:CUR2)

PL/SQL 过程已成功完成。

SQL> PRINT :CUR2

ID NAME
---------- ------------------------------
1 DEF$_TEMP$LOB
2 HELP
3 MVIEW$_ADV_INDEX
4 MVIEW$_ADV_OWB
5 MVIEW$_ADV_PARTITION

把获取远端数据库的游标修改为打开一个从远端数据库表取数据的本地游标。

根据游标的定义,游标应该是Oracle为了处理SQL语句而申请的一块内容区域。而传递游标实际上就是传递的内存的指针。将一个数据库中的游标传递到另一个数据库中,在A数据库中指向一个执行固定结果集的游标,在B数据库中可能指向的就是未分配的内存区域。因此,在数据库之间传递游标显然是不可行的。