使用动态PIVOT时PL / SQL出错

时间:2018-05-30 14:23:07

标签: oracle plsql pivot

我试图创建一个动态PIVOT命令,因为我不知道" in"中需要的确切列数。条款。这种方法的问题是我在执行 立即之后收到错误,其中表示即使预期值匹配,数据类型也不一致。我也尝试使用sys_refcursor但发生了同样的错误。它可能是什么?

    set serveroutput on;
    declare 
      storage_var clob;
      storage_query clob;
      type table_model is table of varchar2(100) index by pls_integer;
      tabl table_model;
    begin

     SELECT DISTINCT LISTAGG('''' || scd_local.descricao || '''',',')
     WITHIN GROUP (ORDER BY scd_local.descricao) INTO storage_var FROM  scd_local; 
     --Creates a list of values to to be used in the pivot command

     storage_query := 'select * from (select doc.nome, loc.descricao 
                    from scd_documento doc, scd_local_doc doc_loc, scd_local loc 
                    where doc.nome = doc_loc.id_doc and loc.id = doc_loc.id_local 
                    order by 1, 2)
                    pivot 
                    (max(descricao) for descricao in ( ' || storage_var || ' ))';

     dbms_output.put_line(storage_query);

     execute immediate storage_query bulk collect into tabl;  
     --Gives an error: "inconsistent datatypes: expected %s got %s"

     for i in 1.. tabl.count 
     loop
       dbms_output.put_line(tabl(i));
     end loop;
    end;
    /

模型

enter image description here

2 个答案:

答案 0 :(得分:2)

另外,您不需要在查询中使用表格SCD_DOCUMENTO

问题在于您将一个可变数量的值提取到结构中:动态查询给出的结果是列数取决于表中的值,因此您无法预先知道有多少列结果会有。

这样,您无法将结果提取到固定数量的结构中,因为您在编译时不知道需要使用多少变量来获取结果。

答案 1 :(得分:0)

正如评论中指出的那样,游标的未知列结构将使得将结果提取到PL / SQL变得非常困难。

但是,如果您真正要做的就是通过DBMS_OUTPUT将结果发送回客户端,您实际上可以使用DBMS_OUTPUT.RETURN_RESULTS执行此操作。

以下是PL / SQL块的修改版本,它打印来自DBA_OBJECTS的用户和对象类型的交叉表,每个单元格显示给定用户拥有的给定类型的对象数。

declare 
  storage_var clob;
  storage_query clob;
  l_ref_cur SYS_REFCURSOR;
begin

 SELECT LISTAGG('''' || o.object_type || '''',',')
 WITHIN GROUP ( ORDER BY o.object_type)
 INTO   storage_var
 FROM ( SELECT DISTINCT OBJECT_TYPE FROM dba_objects ) o;

 storage_query := 'select *
                   from ( SELECT owner, object_type FROM dba_objects ) o
                   pivot
                   (count(*) for object_type in (' || storage_var || '))
                   order by 1';


 dbms_output.put_line(storage_query);

 OPEN l_ref_cur FOR storage_query;  
 dbms_sql.return_result(l_ref_cur);
end;
/