3

这是我的第一个(已编辑)stackoverflow 问题,所以请多多包涵。

在 Oracle 11g 中,我需要描述/询问通过 dblink 从另一个数据库上的过程调用返回的引用游标的基础列,其中实际的 SQL 并不总是“显式”的,但有时是动态生成的。

例如:

declare
    v_ref_cur sys_refcursor;
    v_cur_num number;
    v_col_count number;
    v_col_table dbms_sql.desc_tab3;
begin
    myProc@myDblink(v_ref_cur, 'myvalue');
    v_cur_num := dbms_sql.to_cursor_number(v_ref_cur);
    dbms_sql.describe_columns3(v_cur_num, v_col_count, v_col_table);
    ...
end

如果另一个数据库上的 myProc() 具有“显式”SQL 语句,例如:

open cursor for select * from foo where bar = myParam;

游标转换和描述(仍然)工作得很好——我可以确定过程返回的列名、类型、长度等。

但是,如果另一个数据库上的 myProc() 涉及动态 SQL,例如:

v_sql := 'select * from foo where bar = ''' || myParam || '''';
open cursor for v_sql;

尝试调用 dbms_sql.to_cursor_number() 时出现 ORA-01001 无效游标错误。

有没有办法转换/描述从远程过程调用的动态 SQL 派生的引用游标?如果是这样,怎么做?如果不是,为什么不呢?

感谢您的任何/所有帮助!

4

1 回答 1

0

跨数据库链接使用 DBMS_SQL 会引发许多不同的错误,其中至少有一些是 Oracle 错误。这些问题可以通过将所有逻辑放在远程服务器上编译的函数中来避免。然后远程调用该函数。

--Create and test a database link
create database link myself connect to <schema> identified by "<password>"
    using '<connect string or service name>';
select * from dual@myself;

--myProc
create procedure myProc(p_cursor in out sys_refcursor, p_value varchar2) is
begin
    --open p_cursor for select * from dual where dummy = p_value;
    open p_cursor for 'select * from dual where dummy = '''||p_value||'''';
end;
/

--Simple function that counts and displays the columns.  Expected value is 1.
create or replace function count_columns return number is
    v_ref_cur sys_refcursor;
    v_cur_num number;
    v_col_count number;
    v_col_table dbms_sql.desc_tab3;
begin
    --ORA-01001: invalid cursor
    --myProc@myself(v_ref_cur, 'myvalue');
    myProc(v_ref_cur, 'myvalue');
    --ORA-03113: end-of-file on communication channel
    --v_cur_num := dbms_sql.to_cursor_number@myself(v_ref_cur);
    v_cur_num := dbms_sql.to_cursor_number(v_ref_cur);
    --Compilation error: PLS-00306: 
    --    wrong number or types of arguments in call to 'DESCRIBE_COLUMNS3'
    --dbms_sql.describe_columns3@myself(v_cur_num, v_col_count, v_col_table);
    dbms_sql.describe_columns3(v_cur_num, v_col_count, v_col_table);
    return v_col_count;
end;
/

begin
    dbms_output.put_line('Number of columns: '||count_columns@myself());
end;
/

Number of columns: 1
于 2013-09-26T17:55:03.940 回答