Oracle
 sql >> Baza danych >  >> RDS >> Oracle

Oracle - kursor używający dbms_utility.exec_ddl_statement nie działa poprawnie

DBMS_UTILITY.EXEC_DDL_STATEMENT tylko niezawodnie uruchamia DDL. Jeśli spróbujesz uruchomić go z blokiem PL/SQL, po cichu zawiedzie i nie uruchomi niczego.

Można to zademonstrować, uruchamiając blok PL/SQL, który oczywiście powinien się nie powieść. Poniższy kod powinien generuj ORA-01476: divisor is equal to zero . Ale zamiast tego nic nie robi.

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

Użyj tymczasowej procedury, aby zdalnie uruchomić blok PL/SQL. Utwórz procedurę za pomocą DBMS_UTILITY.EXEC_DDL_STATEMENT a następnie wywołaj go za pomocą natywnego dynamicznego 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

Myślę, że to zachowanie jest błędem. Oracle powinno zgłosić błąd zamiast po prostu nic nie robić.

Witaj w piekle konkatenacji. Struny stają się bałaganem, gdy są osadzone na 4 poziomy. Jest jednak kilka rzeczy, które możesz zrobić, aby ułatwić życie:

  1. Użyj zagnieżdżonego mechanizmu cytowania alternatywnego. Na przykład q'[ ... ]' , wewnątrz q'< ... >' itp.
  2. Użyj ciągów wielowierszowych. Nie ma potrzeby łączenia wielu linii, wystarczy użyć jednego ciągu.
  3. Użyj dodatkowych odstępów, aby zidentyfikować początek i koniec ciągów. Kiedy sprawy przybierają taki szalony obrót, warto postawić sam ogranicznik ciągu w linii, aby wszystko było łatwe do wyrównania.
  4. Użyj REPLACE zamiast konkatenacji.

Korzystając z tych wskazówek, ponownie sformatowałem część kodu. Stackoverflow nie rozumie alternatywnego mechanizmu cytowania, ale ciągi powinny wyglądać lepiej w dobrym edytorze Oracle SQL.

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. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Oracle:Znajdowanie kolumn zawierających tylko wartości null

  2. Klauzula OVER w Oracle

  3. Przejście z LINQpad do właściwego projektu Visual Studio?

  4. ORA-00054:zasób zajęty i pozyskiwanie z określonym NOWAIT lub upłynął limit czasu

  5. Oracle Connection String dla środowiska RAC?