Proč nemůžeme psát příkazy ddl přímo v PL/SQL bloku, například když píšu
CREATE OR REPLACE PROCEDURE test IS
BEGIN
truncate table table_name; // error
END test;
/
Ale,
CREATE OR REPLACE PROCEDURE test IS
BEGIN
execute immediate 'truncate table table_name'; // works fine
END test;
/
Proč druhý úspěšně proveden?
Jak je uvedeno v dokumentace :
Pouze dynamický SQL může provádět následující typy příkazů v programových jednotkách PL/SQL:
- Příkazy jazyka DDL (Data Definition Language) jako CREATE, DROP, GRANT a REVOKE
Operace TRUNCATE
je DDL
.
Při použití EXECUTE IMMEDIATE
, pamatujte, že všechny operace DDL
, které provedete, implicitně COMMIT
aktuální transakci.
DDL uvnitř PL/SQL kódu je více výjimka, než je skutečná potřeba. Parse lze považovat za ověření struktury, které se ztratí, pokud se struktura při provádění změní. Účelem procedur je opět analyzovat další objekty (tabulky nebo jiný kód pl/sql, pohledy atd.). Při každé změně objektu by měl být překompilován. Takže, analyzovaný kód něčeho než struktura změny nemůže být ověřen a jako takový kompilován. Zvažte případ
DROP TABLE T1;
Během analýzy se najde tabulka a procedura se úspěšně zkompiluje, ale při prvním spuštění je tabulka zrušena a váš kód již není platný (příště DROP TABLE by vyústila v chybu). Podobně jakákoli změna v tabulce DDL by vytvořila potřebu překompilovat, a tak ztratit výhodu analýzy kódu.