sql >> Database >  >> RDS >> Oracle

Oracle - cursor die dbms_utility.exec_ddl_statement gebruikt, wordt niet correct uitgevoerd

DBMS_UTILITY.EXEC_DDL_STATEMENT draait alleen betrouwbaar DDL. Als je het probeert uit te voeren met een PL/SQL-blok, zal het stil mislukken en wordt er niets uitgevoerd.

Dit kan worden aangetoond door een PL/SQL-blok uit te voeren dat uiteraard zou moeten mislukken. De onderstaande code moet genereer ORA-01476: divisor is equal to zero . Maar in plaats daarvan doet het niets.

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

Gebruik een tijdelijke procedure om een ​​PL/SQL-blok op afstand uit te voeren. Maak de procedure met DBMS_UTILITY.EXEC_DDL_STATEMENT en roep het dan aan met native dynamische 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

Ik denk dat dit gedrag een bug is. Oracle zou een foutmelding moeten geven in plaats van simpelweg niets te doen.

Welkom in de aaneenschakeling van de hel. Strings worden rommelig als ze 4 niveaus diep zijn ingebed. Maar er zijn een paar dingen die u kunt doen om het leven gemakkelijker te maken:

  1. Gebruik geneste alternatieve aanhalingstekens. Bijvoorbeeld q'[ ... ]' , in een q'< ... >' , enz.
  2. Gebruik tekenreeksen met meerdere regels. Het is niet nodig om meerdere regels samen te voegen, gebruik gewoon een enkele string.
  3. Gebruik extra spaties om het begin en einde van tekenreeksen te identificeren. Als de dingen zo gek worden, is het de moeite waard om alleen een tekenreeksscheidingsteken op een regel te plaatsen, zodat alles gemakkelijk op een rij kan worden gezet.
  4. Gebruik REPLACE in plaats van aaneenschakeling.

Ik heb een deel van je code opnieuw geformatteerd met behulp van die tips. Stackoverflow begrijpt het alternatieve aanhalingsmechanisme niet, maar de strings zouden er beter uit moeten zien in een goede Oracle SQL-editor.

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. Meerdere databases in docker en docker-compose

  2. Autocomplete Textbox-resultaten op basis van SQL-database

  3. hoe het wachtwoord van de rootgebruiker in de MySQL-workbench opnieuw in te stellen

  4. Kan de waarde die ik wilde selecteren niet ophalen met behulp van Opgeslagen procedure