Używanie dynamicznego sql do wyniku, w którym kolumny są nieznane w momencie wykonywania, jest trochę kłopotliwe w Oracle w porównaniu z niektórymi innymi RDMBS.
Ponieważ typ rekordu dla wyjścia jest jeszcze nieznany, nie można go wcześniej zdefiniować.
W Oracle 11g jednym ze sposobów jest użycie bezimiennej procedury, która generuje tymczasową tabelę z przestawnym wynikiem.
Następnie wybierz wyniki z tej tabeli tymczasowej.
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;
Zwroty:
ID adam john rob terry
-- ---- ---- --- -----
1 x x x
2 x
Test na db<>skrzypce znajdziesz tutaj
W Oracle 11g kolejny fajny trik (stworzony przez Antona Scheffera) do wykorzystania można znaleźć na tym blogu. Ale musisz dodać do niego funkcję przestawną.
Kod źródłowy można znaleźć w tym zip
Po tym SQL może być tak prosty, jak ten:
select * from
table(pivot('SELECT ID, CCL, Flag FROM TableA'));
Test na db<>skrzypce znajdziesz tutaj