Използването на динамичен sql за резултат, при който колоните са неизвестни към момента на изпълнение, е малко проблем в Oracle в сравнение с някои други RDMBS.
Тъй като типът на записа за изхода все още е неизвестен, той не може да бъде дефиниран предварително.
В Oracle 11g един от начините е да използвате безименна процедура, която генерира временна таблица с завъртящия се резултат.
След това изберете резултатите от тази временна таблица.
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;
Връща:
ID adam john rob terry
-- ---- ---- --- -----
1 x x x
2 x
Можете да намерите тест за db<>fiddle тук
В Oracle 11g, друг страхотен трик (създаден от Антон Шефер), който да се използва, може да бъде намерен в този блог. Но ще трябва да добавите функцията за въртене за него.
Изходният код може да бъде намерен в този zip
След това SQL може да бъде толкова прост като това:
select * from
table(pivot('SELECT ID, CCL, Flag FROM TableA'));
Тук ще намерите тест за db<>fiddle