将单行结果集转换为关联数组

时间:2011-04-23 21:16:21

标签: oracle select plsql associative-array

说,我有以下查询:

select 1 foo, 2 bar, 3 baz from dual;

基本上,这个查询总是返回一行。我需要创建一个关联数组,其中之一:

arr('foo') = 1;
arr('bar') = 2;
arr('baz') = 3;

我知道结果集只有一行。我既不知道列数量也不知道列名称。

有什么想法吗?

感谢。

UPD:

我的一位朋友发现了一个优秀且优雅的XML解决方案:

  SELECT
   XMLTYPE(EXTRACT(VALUE(T), '/*') .GETSTRINGVAL()) .GETROOTELEMENT() NODE,
   EXTRACTVALUE(COLUMN_VALUE, '/*') NODEVALUE
    FROM
   TABLE(XMLSEQUENCE(XMLTYPE((CURSOR
   (
      --this is the query that needs to be transformed
      SELECT
       *
        FROM
       some_table
       WHERE some_table.id = 123

   )
   )) .EXTRACT('/ROWSET/ROW/*'))) T;

2 个答案:

答案 0 :(得分:2)

这是一个简单的包,它从键值对表中填充关联数组。这很容易。

create or replace package dynaa as
    procedure pop;
    procedure print;
end;
/

create or replace package body dynaa as

    type aa is table of number
        index by varchar2(30);
    this_aa aa;

    procedure pop
    is
    begin
        for r in ( select * from t42 )
        loop
            this_aa (r.id) := r.col1;
        end loop;
    end pop    ;

    procedure print
    is
        idx varchar2(30);
    begin
        idx := this_aa.first();
        while idx is not null
        loop
            dbms_output.put_line(idx ||'='||this_aa(idx));
            idx := this_aa.next(idx);
        end loop;
    end print;
end;
/

它的工作非常巧妙......

SQL> set serveroutput on
SQL>
SQL> exec dynaa.pop

PL/SQL procedure successfully completed.

SQL> exec dynaa.print
DAISY HEAD MAISIE=6969
FOX IN SOCKS=4242
MR KNOX=2323

PL/SQL procedure successfully completed.

SQL>

但是你想要的更复杂:在不知道查询投影的情况下动态填充数组。以下是一个非常简单的实现,如果有问题的表包含单行,它将起作用。它可以很容易地扩展到处理多行的表。

我们重载了POP()程序:

procedure pop
    ( tabname user_tab_columns.table_name%type );

procedure pop
    ( tabname user_tab_columns.table_name%type );
is
    n number;
begin
    for r in ( select column_name 
               from user_tab_columns
               where table_name = tabname)
    loop
        execute immediate 'select '||r.column_name||' from '||tabname into n;
        this_aa (r.column_name) := n;
    end loop;
end pop    ;

所以,这也有效:

SQL> exec dynaa.pop('T23')

PL/SQL procedure successfully completed.

SQL>
SQL> exec dynaa.print
COL1=2323
COL2=4242
COL3=6969

PL/SQL procedure successfully completed.

SQL>

我并不太担心以如此笨拙的方式初始化阵列所带来的性能损失。鉴于记录保留在缓存中,这并不算太糟糕。如果你经常调用POP()表示性能确实成为一个问题,那么你可能不应该首先使用关联数组:常规查找或结果集缓存是更好的选择。

答案 1 :(得分:1)

一个很简短的答案是使用DBMS_SQL包查看旧式(Oracle 9之前版本)动态SQL。您可以使用DESCRIBE_COLUMNS获取列的数量(和数据类型),并COLUMN_VALUEDESCRIBE_COLUMNS返回的PL / SQL表中的每个条目单独获取每个列值。

之后,将一行转换为关联数组非常容易。