2011-04-23 50 views
2

说,我有以下查询:转化单行结果集到一个关联数组

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

下面是一个简单的包,其填充从密钥值对表的关联数组。这是一个简单的例子。

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> 

我不是太担心初始化数组中这样的shonky时尚的性能损失。鉴于记录停留在缓存中,这并不算太坏。如果您经常打电话POP(),以至于性能确实成为问题,那么您可能不应该首先使用关联数组:定期查找或结果集缓存将是更好的选择。

1

一个非常简短的回答是看旧式(预甲骨文9)动态SQL使用DBMS_SQL包。您可以使用DESCRIBE_COLUMNS获得数量(和数据类型)列并COLUMN_VALUE在通过DESCRIBE_COLUMNS返回单独提取每个列值的PL/SQL表中的每个条目。

在那之后,它很容易把一行到关联数组。