At bruge dynamisk sql til et resultat, hvor kolonnerne er ukendte på udførelsestidspunktet, er lidt besværligt i Oracle sammenlignet med visse andre RDMBS.
Da posttypen for outputtet endnu er ukendt, kan den ikke defineres på forhånd.
I Oracle 11g er en måde at bruge en navnløs procedure, der genererer en midlertidig tabel med det pivoterede resultat.
Vælg derefter resultaterne fra den midlertidige tabel.
declare
v_sqlqry clob;
v_cols clob;
begin
-- Generating a string with a list of the unique names
select listagg(''''||CCL||''' as "'||CCL||'"', ', ') within group (order by CCL)
into v_cols
from
(
select distinct CCL
from tableA
);
-- drop the temporary table if it exists
EXECUTE IMMEDIATE 'DROP TABLE tmpPivotTableA';
EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF;
-- A dynamic SQL to create a temporary table
-- based on the results of the pivot
v_sqlqry := '
CREATE GLOBAL TEMPORARY TABLE tmpPivotTableA
ON COMMIT PRESERVE ROWS AS
SELECT *
FROM (SELECT ID, CCL, Flag FROM TableA) src
PIVOT (MAX(Flag) FOR (CCL) IN ('||v_cols||')) pvt';
-- dbms_output.Put_line(v_sqlqry); -- just to check how the sql looks like
execute immediate v_sqlqry;
end;
/
select * from tmpPivotTableA;
Returneringer:
ID adam john rob terry
-- ---- ---- --- -----
1 x x x
2 x
Du kan finde en test på db<>fiddle her
I Oracle 11g kan du finde et andet sejt trick (skabt af Anton Scheffer), der skal bruges i denne blog. Men du bliver nødt til at tilføje pivotfunktionen til det.
Kildekoden kan findes i denne zip
Derefter kan SQL'en være så enkel som denne:
select * from
table(pivot('SELECT ID, CCL, Flag FROM TableA'));
Du finder en test på db<>fiddle her