首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Oracle -从引用游标中选择特定列

问Oracle -从引用游标中选择特定列
EN

Stack Overflow用户
提问于 2012-04-26 02:25:56
回答 3查看 31.5K关注 0票数 11

我有一个名为Table1的表。它有很多列,其中之一是Column1。我不知道其他的栏目,它们有时甚至可能会改变。有一个强类型的引用游标类型,它返回Table1%rowtype,名为cur_Table1。我有一个名为SP1的存储过程,它有一个cur_Table1类型的out参数。我从另一个数据库调用此SP1存储过程,该数据库只看到此存储过程,而不能看到表或类型本身。如何从返回的游标中仅选择Column1?我知道我可以提取到一条记录或与游标包含的列一样多的变量,但我只知道一列的存在,所以我不能声明完整的记录或正确的变量数量。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-04-26 14:03:07

你可以用DBMS_SQL来做这件事,但是它并不美观。

表和示例数据(COLUMN1的数字为1- 10):

代码语言:javascript
复制
create table table1(column1 number, column2 date, column3 varchar2(1000), column4 clob);

insert into table1
select level, sysdate, level, level from dual connect by level <= 10;
commit;

包含打开引用游标并选择所有内容的过程的包:

代码语言:javascript
复制
create or replace package test_pkg is
    type cur_Table1 is ref cursor return table1%rowtype;
    procedure sp1(p_cursor in out cur_table1);
end;
/

create or replace package body test_pkg is
    procedure sp1(p_cursor in out cur_table1) is
    begin
        open p_cursor for select column1, column2, column3, column4 from table1;
    end;
end;
/

从引用游标读取COLUMN1数据的PL/SQL块:

代码语言:javascript
复制
--Basic steps are: call procedure, convert cursor, describe and find columns,
--then fetch rows and retrieve column values.
--
--Each possible data type for COLUMN1 needs to be added here.
--Currently only NUMBER is supported.
declare
    v_cursor sys_refcursor;
    v_cursor_number number;

    v_columns number;
    v_desc_tab dbms_sql.desc_tab;
    v_position number;
    v_typecode number;
    v_number_value number;
begin
    --Call procedure to open cursor
    test_pkg.sp1(v_cursor);
    --Convert cursor to DBMS_SQL cursor
    v_cursor_number := dbms_sql.to_cursor_number(rc => v_cursor);
    --Get information on the columns
    dbms_sql.describe_columns(v_cursor_number, v_columns, v_desc_tab);

    --Loop through all the columns, find COLUMN1 position and type
    for i in 1 .. v_desc_tab.count loop
        if v_desc_tab(i).col_name = 'COLUMN1' then
            v_position := i;
            v_typecode := v_desc_tab(i).col_type;

            --Pick COLUMN1 to be selected.
            if v_typecode = dbms_types.typecode_number then
                dbms_sql.define_column(v_cursor_number, i, v_number_value);
            --...repeat for every possible type.
            end if;
        end if;
    end loop;

    --Fetch all the rows, then get the relevant column value and print it
    while dbms_sql.fetch_rows(v_cursor_number) > 0 loop
        if v_typecode = dbms_types.typecode_number then
            dbms_sql.column_value(v_cursor_number, v_position, v_number_value);
            dbms_output.put_line('Value: '||v_number_value);
        --...repeat for every possible type
        end if;
    end loop;   
end;
/
票数 8
EN

Stack Overflow用户

发布于 2012-04-27 14:38:44

考虑到最初的问题,jonearles的答案仍然是正确的,所以我将把它标记为正确的,但我最终做了完全不同的事情,而且做得更好。

问题是我无法控制SP1的数据库,我只能作为第三方客户端从别处调用它。现在,我成功地获得了权限,不仅可以查看SP,还可以查看光标的类型。我仍然没有看到表,但现在有了一个更清晰的解决方案:

在另一个数据库中,我现在已被授予查看此类型的权限:

代码语言:javascript
复制
type cur_Table1 is ref cursor return Table1%rowtype;

因此,在我的数据库中,我现在可以这样做:

代码语言:javascript
复制
mycursor OtherDB.cur_Table1;
myrecord mycursor%rowtype;
...
OtherDB.SP1(mycursor);
fetch mycursor into myrecord;
dbms_output.put_line(myrecord.Column1);

看,我仍然不需要对表的任何访问权限,我只看到光标。关键是神奇的%rowtype同样适用于游标,而不仅仅是表。它在sys_refcursor上不起作用,但在强类型上起作用。有了这段代码,我不需要关心另一端是否有任何变化,我根本不需要定义所有列或记录,我只需要指定我感兴趣的一列。

我真的很喜欢甲骨文这种面向对象的态度。

票数 4
EN

Stack Overflow用户

发布于 2012-04-26 03:33:57

我不知道这是否是一个选项,但创建一个返回您正在查找的特定值的函数不是更好的解决方案吗?这避免了发送额外数据的开销。或者,您可以定义一个游标,其中包含一组双方都知道的已知字段。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10321571

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档