DBMS_UTILITY.EXEC_DDL_STATEMENT
läuft nur zuverlässig DDL. Wenn Sie versuchen, es mit einem PL/SQL-Block auszuführen, schlägt es stillschweigend fehl und es wird nichts ausgeführt.
Dies kann demonstriert werden, indem ein PL/SQL-Block ausgeführt wird, der offensichtlich fehlschlagen sollte. Der folgende Code sollte generieren ORA-01476: divisor is equal to zero
. Aber stattdessen tut es nichts.
begin
[email protected](
q'[declare v_test number; begin v_test := 1/0; end;]'
);
end;
/
Verwenden Sie eine temporäre Prozedur, um einen PL/SQL-Block remote auszuführen. Erstellen Sie die Prozedur mit DBMS_UTILITY.EXEC_DDL_STATEMENT
und rufen Sie es dann mit nativem dynamischem SQL auf.
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
Ich halte dieses Verhalten für einen Bug. Oracle sollte einen Fehler ausgeben, anstatt einfach nichts zu tun.
Willkommen in der Verkettungshölle. Strings werden unordentlich, wenn sie 4 Ebenen tief eingebettet sind. Aber es gibt ein paar Dinge, die Sie tun können, um das Leben einfacher zu machen:
- Verwenden Sie einen verschachtelten alternativen Zitiermechanismus. Beispiel:
q'[ ... ]'
, innerhalb einesq'< ... >'
usw. - Verwenden Sie mehrzeilige Zeichenfolgen. Es ist nicht nötig, mehrere Zeilen zu verketten, verwenden Sie einfach einen einzelnen String.
- Verwenden Sie zusätzliche Leerzeichen, um den Anfang und das Ende von Zeichenfolgen zu identifizieren. Wenn die Dinge so verrückt werden, lohnt es sich, ein String-Trennzeichen ganz allein auf eine Zeile zu setzen, damit alles einfach aneinandergereiht werden kann.
- Verwenden Sie
REPLACE
statt Verkettung.
Ich habe einen Teil Ihres Codes mit diesen Tipps neu formatiert. Stackoverflow versteht den alternativen Quoting-Mechanismus nicht, aber die Strings sollten in einem guten Oracle SQL-Editor besser aussehen.
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;
/