繁体   English   中英

如何在动态 pl sql (oracle sql)中将不同的列转为行

[英]How to Unpivot different columns into rows in dynamic pl sql (oracle sql)

如何使用动态 pl sql 将几个不同的列转为几个不同的行? 使用 static sql 它运行良好,但使用动态 sql 我不断出错。 Static sql 工作正常:

SELECT A, B, C, D from table UNPIVOT (
(A,B,C,D) FOR values in (
                        (A_1, B_1, C_1, D_1)as 'cat1',
                        (A_2, B_2, C_2, D_2)as 'cat2',
                        (A_3, B_3, C_3, D_3)as 'cat3',
                        (A_4, B_4, C_4, D_4)as 'cat4'
))p 

但是,当我尝试将相同的代码转换为动态 sql 时,它不起作用,我收到错误,例如缺少正确的动态 sql:

Declare 
col_list_A  CLOB;
col_list_B  CLOB;
col_list_C  CLOB;
col_list_D  CLOB;
Viewsql    CLOB;

Begin


SELECT  listagg(column_name,',') WITHIN GROUP(ORDER BY column_name)
INTO col_list_A FROM all_tab_columns
WHERE table_name = 'table_xxx' and column_name like 'A_%' ;   

SELECT  listagg(column_name,',') WITHIN GROUP(ORDER BY column_name)
INTO col_list_B FROM all_tab_columns
WHERE table_name = 'table_xxx' and column_name like 'B_%' ;    

SELECT  listagg(column_name,',') WITHIN GROUP(ORDER BY column_name)
INTO col_list_C FROM all_tab_columns
WHERE table_name = 'table_xxx' and column_name like 'C_%' ;    

SELECT  listagg(column_name,',') WITHIN GROUP(ORDER BY column_name)
INTO col_list_D FROM all_tab_columns
WHERE table_name = 'table_xxx' and column_name like 'D_%' ;    

 

Viewsql := 'SELECT A,B,C,D,VAL_NAME FROM table_xxx UNPIVOT (
(A,B,C,D) FOR VAL_NAME IN ('||col_list_A ||','||col_list_B ||','||col_list_C ||','||col_list_D ||')' ; 

execute immediate 'CREATE or REPLACE VIEW table_xxx_view AS ' || viewsql;

End;
/
select * from table_xxx_view

当我执行上述动态 sql 时,我得到“缺少右括号”错误。

但是,当我修改动态 sql 查询并将 A 列与 col_list_A 一起取消透视时,查询成功。 下面的动态查询是成功的:


Declare 
col_list_A  CLOB;
Viewsql    CLOB;

Begin


SELECT  listagg(column_name,',') WITHIN GROUP(ORDER BY column_name)
INTO col_list_A FROM all_tab_columns
WHERE table_name = 'table_xxx' and column_name like 'A_%' ; 

Viewsql := 'SELECT A,VAL_NAME FROM table_xxx UNPIVOT (
A FOR VAL_NAME IN ('||col_list_A ||')' ; 

execute immediate 'CREATE or REPLACE VIEW table_xxx_view AS ' || viewsql;

End;
/
select * from table_xxx_view

在此先感谢各位

使用动态 SQL 时,最好显示您将要执行的语句,然后——一旦你确定它没问题——实际执行它。

因此,如果您将过程的结尾修改为

<snip>
dbms_output.put_line(viewsql);

--execute immediate 'CREATE or REPLACE VIEW table_xxx_view AS ' || viewsql;
end;

您可以将您准备的内容与您的预期进行比较。


对于样本表:

SQL> create table "table_xxx"
  2  (a_1 number, a_2 number, a_3 number, a_4 number,
  3   b_1 number, b_2 number, b_3 number, b_4 number,
  4   c_1 number, c_2 number, c_3 number, c_4 number,
  5   d_1 number, d_2 number, d_3 number, d_4 number);

Table created.

SQL>

这是您的 static SQL (即,这就是您所期望的)(尽管稍作修改;此外,它没有返回任何内容,但它是正确的):

SQL> SELECT A, B, C, D from "table_xxx" UNPIVOT (
  2  (A,B,C,D) FOR val_name in (
  3                          (A_1, B_1, C_1, D_1)as 'cat1',
  4                          (A_2, B_2, C_2, D_2)as 'cat2',
  5                          (A_3, B_3, C_3, D_3)as 'cat3',
  6                          (A_4, B_4, C_4, D_4)as 'cat4'
  7  ))p;

no rows selected

SQL>

另一方面,这是您的过程返回的结果:

SQL> set serveroutput on
SQL>
SQL> Declare
  2      col_list_A  CLOB;
  3      col_list_B  CLOB;
  4      col_list_C  CLOB;
  5      col_list_D  CLOB;
  6      Viewsql    CLOB;
  7  Begin
  8      SELECT  listagg(column_name,',') WITHIN GROUP(ORDER BY column_name)
  9      INTO col_list_A FROM all_tab_columns
 10      WHERE table_name = 'table_xxx' and column_name like 'A_%' ;
 11
 12      SELECT  listagg(column_name,',') WITHIN GROUP(ORDER BY column_name)
 13      INTO col_list_B FROM all_tab_columns
 14      WHERE table_name = 'table_xxx' and column_name like 'B_%' ;
 15
 16      SELECT  listagg(column_name,',') WITHIN GROUP(ORDER BY column_name)
 17      INTO col_list_C FROM all_tab_columns
 18      WHERE table_name = 'table_xxx' and column_name like 'C_%' ;
 19
 20      SELECT  listagg(column_name,',') WITHIN GROUP(ORDER BY column_name)
 21      INTO col_list_D FROM all_tab_columns
 22      WHERE table_name = 'table_xxx' and column_name like 'D_%' ;
 23
 24      Viewsql := 'SELECT A,B,C,D,VAL_NAME FROM table_xxx UNPIVOT (
 25      (A,B,C,D) FOR VAL_NAME IN ('||col_list_A ||','||col_list_B ||','||col_list_C ||','||col_list_D ||')' ;
 26
 27      dbms_output.put_Line(viewsql);
 28
 29      --execute immediate 'CREATE or REPLACE VIEW table_xxx_view AS ' || viewsql;
 30  End;
 31  /

结果:

SELECT A,B,C,D,VAL_NAME FROM table_xxx UNPIVOT (
    (A,B,C,D) FOR VAL_NAME IN
(A_1,A_2,A_3,A_4,B_1,B_2,B_3,B_4,C_1,C_2,C_3,C_4,D_1,D_2,D_3,D_4)

PL/SQL procedure successfully completed.

SQL>

很明显,你得到的并不符合你的期望。

因此,回到绘图板并修复程序,使其返回正确的结果。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM