sql >> Databasteknik >  >> RDS >> Oracle

Oracle - markören som använder dbms_utility.exec_ddl_statement körs inte korrekt

DBMS_UTILITY.EXEC_DDL_STATEMENT kör endast DDL på ett tillförlitligt sätt. Om du försöker köra det med ett PL/SQL-block kommer det tyst att misslyckas och inte köra någonting.

Detta kan demonstreras genom att köra ett PL/SQL-block som uppenbarligen skulle misslyckas. Koden nedan bör generera ORA-01476: divisor is equal to zero . Men istället gör det ingenting.

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

Använd en tillfällig procedur för att köra ett PL/SQL-block på distans. Skapa proceduren med DBMS_UTILITY.EXEC_DDL_STATEMENT och sedan anropa den med inbyggd dynamisk 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

Jag tror att detta beteende är en bugg. Oracle borde skicka ett fel istället för att helt enkelt inte göra någonting.

Välkommen till sammanlänkningshelvetet. Strängar blir röriga när de är inbäddade 4 nivåer djupa. Men det finns några saker du kan göra för att göra livet enklare:

  1. Använd kapslade alternativa citatmekanismer. Till exempel, q'[ ... ]' , inuti en q'< ... >' osv.
  2. Använd flerradiga strängar. Det finns inget behov av att sammanfoga flera rader, använd bara en enda sträng.
  3. Använd extra mellanrum för att identifiera början och slutet av strängar. När det blir så här galet är det värt att sätta en strängavgränsare på en linje helt för sig, så att allt är lätt att rada upp.
  4. Använd REPLACE istället för sammanlänkning.

Jag formaterade om en del av din kod med hjälp av dessa tips. Stackoverflow förstår inte den alternativa citeringsmekanismen, men strängarna borde se bättre ut i en bra Oracle SQL-redigerare.

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. Hur jämför man två frågeresultat för jämlikhet i MySQL?

  2. Vilka är fördelarna med att använda migrationer och modellklasser i Laravel?

  3. Mysql php teckenuppsättning inställning

  4. cakephp lägger till post med vissa parametrar fixade