Oracle
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Oracle

Oracle - con trỏ sử dụng dbms_utility.exec_ddl_statement không thực thi đúng cách

DBMS_UTILITY.EXEC_DDL_STATEMENT chỉ chạy DDL một cách đáng tin cậy. Nếu bạn cố gắng chạy nó với một khối PL / SQL, nó sẽ âm thầm bị lỗi và không chạy được gì.

Điều này có thể được chứng minh bằng cách chạy một khối PL / SQL mà rõ ràng sẽ không thành công. Đoạn mã dưới đây nên tạo ORA-01476: divisor is equal to zero . Nhưng thay vào đó, nó không làm gì cả.

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

Sử dụng thủ tục tạm thời để chạy khối PL / SQL từ xa. Tạo quy trình với DBMS_UTILITY.EXEC_DDL_STATEMENT và sau đó gọi nó bằng SQL động nguyên bản.

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

Tôi nghĩ rằng hành vi này là một lỗi. Oracle nên đưa ra một lỗi thay vì chỉ đơn giản là không làm gì cả.

Chào mừng đến với địa ngục nối. Các chuỗi trở nên lộn xộn khi chúng được nhúng sâu 4 cấp. Nhưng có một số điều bạn có thể làm để giúp cuộc sống dễ dàng hơn:

  1. Sử dụng cơ chế trích dẫn thay thế lồng nhau. Ví dụ:q'[ ... ]' , bên trong q'< ... >' , v.v.
  2. Sử dụng các chuỗi nhiều dòng. Không cần phải nối nhiều dòng, chỉ cần sử dụng một chuỗi duy nhất.
  3. Sử dụng thêm khoảng cách để giúp xác định điểm bắt đầu và kết thúc của chuỗi. Khi mọi thứ trở nên điên rồ, bạn nên đặt một dấu phân cách chuỗi trên một dòng để mọi thứ trở nên dễ dàng.
  4. Sử dụng REPLACE thay vì nối.

Tôi đã định dạng lại một phần mã của bạn bằng các mẹo đó. Stackoverflow không hiểu cơ chế trích dẫn thay thế, nhưng các chuỗi sẽ trông đẹp hơn trong trình soạn thảo Oracle SQL tốt.

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. cách sử dụng các mục nhập tns với trình điều khiển macromedia cho Oracle

  2. Truy vấn đệ quy cho các phụ thuộc bảng không đệ quy không nhiều như tôi muốn

  3. Lấy tổng một số cột từ hai bảng

  4. Ngày-giờ được tạo cho hàng Bảng trong Oracle là gì?

  5. Đếm số bản sao CLOB trong một bảng Oracle lớn