[英]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.