Z dynamicznym SQL są trzy rzeczy.
- EXECUTE IMMEDIATE nie jest funkcją:prawidłowa składnia to
execute immediate '<<query>>' into <<variable>>
. - Instrukcja INSERT przyjmuje klauzulę VALUES lub SELECT, ale nie obie. W tym przypadku SELECT byłby bardzo błędny. Pamiętaj też, że to VALUES, a nie VALUE.
- COLUMN_NAME to literał ciągu w dynamicznym SQL, więc musi być ujęty w cudzysłów. Ale ponieważ instrukcja SQL jest sama w sobie łańcuchem, cudzysłowy w dynamicznych łańcuchach muszą być zmienione, więc powinno to być `'''||nazwa_kolumny||'''.
Tak więc poprawiona wersja będzie wyglądać mniej więcej tak
declare
Cursor C_TABLE is
select trim(table_name) as table_name
from all_tables
where table_name in ('T1', 'T2', 'T3');
V_ROWNUM number;
begin
for m in C_TABLE
loop
for i in ( select column_name
from (
select c.column_name
from all_tab_columns c
where c.table_name = m.table_name
and c.owner = 'owner1'
)
)
loop
execute immediate 'select count(*) from ' || m.table_name into V_ROWNUM;
execute immediate 'insert into MY_table values ( ''' || i.column_name || ''', ' || V_ROWNUM || ')';
end loop;
end loop;
end;
/
Dynamiczny SQL jest trudny, ponieważ zamienia błędy kompilacji w błędy czasu wykonywania. Dobrą praktyką jest pisanie instrukcji najpierw jako statycznego SQL. Gdy już opanujesz podstawową składnię, możesz przekonwertować ją na dynamiczny SQL.