【问题标题】:Transforming single-row result set into an associative array将单行结果集转换为关联数组
【发布时间】:2011-08-11 15:21:53
【问题描述】:

说,我有以下查询:

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

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

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

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

有什么想法吗?

谢谢。

更新:

我的一个朋友发现了一个漂亮而优雅的涉及 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;

【问题讨论】:

    标签: oracle select plsql associative-array


    【解决方案1】:

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

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

    【讨论】:

      【解决方案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() 以至于性能确实成为问题,那么您可能首先不应该使用关联数组:常规查找或结果集缓存会是更好的选择。

      【讨论】:

        猜你喜欢
        • 2011-04-13
        • 2012-01-20
        • 1970-01-01
        • 2018-06-26
        • 1970-01-01
        • 2017-05-03
        • 2014-02-28
        • 2015-12-13
        • 2013-04-12
        相关资源
        最近更新 更多