Oracle
 sql >> Database >  >> RDS >> Oracle

Oracle:il cursore che utilizza dbms_utility.exec_ddl_statement non viene eseguito correttamente

DBMS_UTILITY.EXEC_DDL_STATEMENT esegue solo in modo affidabile DDL. Se provi a eseguirlo con un blocco PL/SQL, fallirà silenziosamente e non eseguirà nulla.

Questo può essere dimostrato eseguendo un blocco PL/SQL che dovrebbe ovviamente fallire. Il codice seguente dovrebbe generate ORA-01476: divisor is equal to zero . Ma invece non fa nulla.

begin
    [email protected](
        q'[declare v_test number; begin v_test := 1/0; end;]'
    );
end;
/

Utilizzare una procedura temporanea per eseguire un blocco PL/SQL in remoto. Crea la procedura con DBMS_UTILITY.EXEC_DDL_STATEMENT e quindi chiamalo con SQL dinamico nativo.

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

Penso che questo comportamento sia un bug. Oracle dovrebbe generare un errore invece di non fare nulla.

Benvenuti nell'inferno della concatenazione. Le stringhe diventano disordinate quando sono incorporate a 4 livelli di profondità. Ma ci sono alcune cose che puoi fare per semplificarti la vita:

  1. Usa il meccanismo di quotazione alternativa annidato. Ad esempio, q'[ ... ]' , all'interno di un q'< ... >' , ecc.
  2. Usa stringhe su più righe. Non è necessario concatenare più righe, basta usare una singola stringa.
  3. Usa spaziatura extra per aiutare a identificare l'inizio e la fine delle stringhe. Quando le cose diventano così pazze, vale la pena mettere un delimitatore di stringa su una riga da solo, in modo che tutto sia facile da allineare.
  4. Usa REPLACE invece della concatenazione.

Ho riformattato parte del tuo codice usando questi suggerimenti. Stackoverflow non comprende il meccanismo di quotazione alternativo, ma le stringhe dovrebbero avere un aspetto migliore in un buon editor SQL Oracle.

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;
/