The following procedure compiles successfully on ctrll + S
(shows VALID) but on execution throws the error : Invalid character error
while executing t
Should be
SQL> CREATE OR REPLACE PROCEDURE pivot (v_recordset OUT SYS_REFCURSOR)
2 AS
3 --v_recordset SYS_REFCURSOR;
4 v_sql LONG;
5 v_cols_1 LONG;
6 v_cols_2 CLOB;
7 BEGIN
8 SELECT LISTAGG ('''' || "level" || ''' AS "' || "level" || '"', ',')
9 WITHIN GROUP (ORDER BY "level" DESC)
10 INTO v_cols_1
11 FROM (SELECT DISTINCT "level"
12 FROM tempt);
13
14 SELECT DBMS_XMLGEN.CONVERT (
15 RTRIM (
16 XMLAGG (XMLELEMENT (
17 e,
18 'MAX(CASE WHEN CATEGORY = '
19 || CHR (39)
20 || CATEGORY
21 || CHR (39)
22 || ' THEN '
23 || CHR (39)
24 || "level"
25 || CHR (39)
26 || ' END) AS '
27 || "level"
28 || '_'
29 || CATEGORY
30 || '',
31 ',')
32 ORDER BY 1 DESC).EXTRACT ('//text()').getclobval (),
33 ','))
34 INTO v_cols_2
35 FROM (SELECT DISTINCT "level", CATEGORY
36 FROM tempt);
37
38 v_sql := 'SELECT "set", ' || v_cols_2 || '
39 FROM
40 (
41 SELECT *
42 FROM tempt
43 PIVOT
44 (
45 MAX(value) FOR "level" IN ( ' || v_cols_1 || ' )
46 )
47 )
48 GROUP BY "set"
49 ORDER BY "set"';
50 v_sql := REPLACE (v_sql, ''', CHR (39));
51 DBMS_OUTPUT.PUT_LINE (v_sql);
52
53 OPEN v_recordset FOR v_sql;
54 END pivot;
55 /
Procedure created.
SQL>
Testing:
SQL> SET SERVEROUTPUT ON
SQL> DECLARE
2 l_rc SYS_REFCURSOR;
3 BEGIN
4 pivot (l_rc);
5 END;
6 /
SELECT "set", MAX(CASE WHEN CATEGORY = 'GHI' THEN 'Y' END) AS Y_GHI,MAX(CASE
WHEN CATEGORY = 'ABC' THEN 'Y' END) AS Y_ABC,MAX(CASE WHEN CATEGORY = 'ABC' THEN
'Z' END) AS Z_ABC,MAX(CASE WHEN CATEGORY = 'DEF' THEN 'Z' END) AS Z_DEF,MAX(CASE
WHEN CATEGORY = 'IJK' THEN 'X' END) AS X_IJK,MAX(CASE WHEN CATEGORY = 'GHI' THEN
'Z' END) AS Z_GHI,MAX(CASE WHEN CATEGORY = 'DEF' THEN 'X' END) AS X_DEF,MAX(CASE
WHEN CATEGORY = 'ABC' THEN 'X' END) AS X_ABC,MAX(CASE WHEN CATEGORY = 'DEF' THEN
'Y' END) AS Y_DEF
FROM
(
SELECT *
FROM tempt
PIVOT
(
MAX(value) FOR "level" IN ( 'Z' AS "Z",'Y' AS
"Y",'X' AS "X" )
)
)
GROUP BY "set"
ORDER BY "set"
PL/SQL procedure successfully completed.
SQL>
Running the resulting query produces the following result (snipped):
SQL> SELECT "set", MAX(CASE WHEN CATEGORY = 'GHI <snip>
ORY = 'DEF' THEN 'Z' END) AS Z_DEF,MAX(CASE WHEN <snip>
(CASE WHEN CATEGORY = 'ABC' THEN 'X' END) AS X_A <snip>
2 FROM
3 (
4 SELECT *
5 FROM tempt
6 PIVOT
7 (
8 MAX(value) FOR "level" IN ( 'Z'
9 )
10 )
11 GROUP BY "set"
12 ORDER BY "set"
13 /
s Y Y Z Z X Z X X Y
- - - - - - - - - -
A Y Y Z Z Z X X Y
B Y Z Z X X X Y
C Y Z Z X X Y
D Y Y Z Z Z X X Y
E Y Z Z X X Y
SQL>
P.S. Forgot to say: really, really, REALLY bad idea naming column using lower case under double quotes.