Oracle
 sql >> база данни >  >> RDS >> Oracle

Oracle - курсорът, използващ dbms_utility.exec_ddl_statement, не се изпълнява правилно

DBMS_UTILITY.EXEC_DDL_STATEMENT надеждно изпълнява само DDL. Ако се опитате да го стартирате с PL/SQL блок, той тихо ще се провали и няма да стартира нищо.

Това може да се демонстрира чрез стартиране на PL/SQL блок, който очевидно трябва да се провали. Кодът по-долу трябва генерира ORA-01476: divisor is equal to zero . Но вместо това не прави нищо.

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

Използвайте временна процедура за отдалечено изпълнение на PL/SQL блок. Създайте процедурата с DBMS_UTILITY.EXEC_DDL_STATEMENT и след това да го извикате със собствен динамичен 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

Мисля, че това поведение е грешка. Oracle трябва да изведе грешка, вместо просто да не прави нищо.

Добре дошли в ада на конкатенацията. Струните се объркват, когато са вградени на 4 нива дълбоко. Но има няколко неща, които можете да направите, за да улесните живота си:

  1. Използване на вложен алтернативен механизъм за цитиране. Например q'[ ... ]' , вътре в q'< ... >' и т.н.
  2. Използвайте многоредови низове. Няма нужда да свързвате няколко реда, просто използвайте един низ.
  3. Използвайте допълнителен интервал, за да идентифицирате началото и края на низовете. Когато нещата станат толкова луди, струва си да поставите разделител на низ на ред сам по себе си, така че всичко да е лесно за подреждане.
  4. Използвайте REPLACE вместо конкатенация.

Преформатирах част от вашия код, използвайки тези съвети. Stackoverflow не разбира алтернативния механизъм за цитиране, но низовете трябва да изглеждат по-добре в добър 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

  2. Повтаряне на една и съща променлива за свързване многократно при използване на динамичната SQL структура OPEN...FOR в Oracle PL/SQL

  3. Не може да се изтрие в базата данни поради ограничения

  4. Списък с елементи на формат за дата и време в Oracle

  5. Замяна на низове на Oracle