DBMS_UTILITY.EXEC_DDL_STATEMENT
spolehlivě spouští pouze DDL. Pokud se jej pokusíte spustit s blokem PL/SQL, tiše selže a nespustí nic.
To lze demonstrovat spuštěním bloku PL/SQL, který by měl zjevně selhat. Níže uvedený kód měl by vygenerovat ORA-01476:dělitel je roven nule
. Ale místo toho nedělá nic.
begin
[email protected](
q'[declare v_test number; begin v_test := 1/0; end;]'
);
end;
/
Ke vzdálenému spuštění bloku PL/SQL použijte dočasnou proceduru. Vytvořte proceduru pomocí DBMS_UTILITY.EXEC_DDL_STATEMENT
a poté jej zavolejte pomocí nativního dynamického SQL.
begin
[email protected](
q'[
create or replace procedure test_procedure
is
v_test number;
begin
v_test := 1/0;
end;
]'
);
execute immediate 'begin [email protected]; end;';
end;
/
RESULTS:
ORA-01476: divisor is equal to zero
ORA-06512: at "JHELLER.TEST_PROCEDURE", line 5
ORA-06512: at line 1
ORA-06512: at line 12
( q'[ vytvořit nebo nahradit proceduru testovací_procedura je číslo v_testu; begin v_test :=1/0; konec; ]' ); spustit okamžitě 'begin examplecom@sqldat.; end;';end;/RESULTS:ORA-01476:dělitel se rovná nuleORA-06512:na "JHELLER.TEST_PROCEDURE", řádek 5ORA-06512:na řádku 1ORA-06512:na řádku 12
Myslím, že toto chování je chyba. Oracle by měl vyvolat chybu místo toho, aby prostě nic nedělal.
Vítejte v pekle zřetězení. Řetězce se zamotají, když jsou vložené 4 úrovně hluboko. Existuje však několik věcí, které můžete udělat, abyste si usnadnili život:
- Použijte vnořený mechanismus alternativních uvozovek. Například
q'[ ... ]'
, uvnitřq'<...>'
atd. - Používejte víceřádkové řetězce. Není třeba spojovat více řádků, stačí použít jeden řetězec.
- Použijte další mezery, které pomohou určit začátek a konec řetězců. Když se věci tak zblázní, stojí za to umístit oddělovač řetězců na řádek úplně sám, aby bylo snadné vše zarovnat.
- Použijte
REPLACE
místo zřetězení.
Pomocí těchto tipů jsem přeformátoval část vašeho kódu. Stackoverflow nerozumí alternativnímu mechanismu citování, ale řetězce by měly vypadat lépe v dobrém Oracle SQL editoru.
declare
v_db_name varchar2(30) := 'myself';
sql_update varchar2(32767);
begin
execute immediate replace(
q'[
begin
[email protected]#DB_NAME#
(
q'<
create or replace procedure cw_drop_table is
sql_drop varchar2(2000);
begin
sql_drop :=
q'{
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE iSecurity2_dupes_bak';
EXCEPTION WHEN OTHERS THEN
IF SQLCODE != -942 THEN
NULL;
END IF;
END;
}';
execute immediate sql_drop;
end;
>'
);
execute immediate 'begin [email protected]#DB_NAME#; end;';
end;
]', '#DB_NAME#', v_db_name);
sql_update := 'create table iSecurity2_dupes_bak as select * from iSecurity2';
execute immediate 'begin [email protected]'||v_db_name||
'(:sql_update); end;' using sql_update;
commit;
end;
/