sql >> Databáze >  >> RDS >> Oracle

Oracle - kurzor používající příkaz dbms_utility.exec_ddl_statement se nespouští správně

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:

  1. Použijte vnořený mechanismus alternativních uvozovek. Například q'[ ... ]' , uvnitř q'<...>' atd.
  2. Používejte víceřádkové řetězce. Není třeba spojovat více řádků, stačí použít jeden řetězec.
  3. 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.
  4. 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;
/



  1. Porovnání data MySQL

  2. připojte mysql k postgresql

  3. Jak vložit záznamy do proměnných z cte v oracle?

  4. Problém s vytvářením souboru .MDF ze sady Visual Studio 2010