2009-11-27 17 views
5

Giả sử tôi có kích hoạt AFTER ALTER trên cơ sở dữ liệu Oracle của mình và tôi đổi tên một số đối tượng cơ sở dữ liệu (ALTER ... RENAME TO ...). Trong trình kích hoạt, làm cách nào để xác định tên mới của đối tượng cơ sở dữ liệu? Dường như các hàm ORA_DICT_OBJ_OWNER, ORA_DICT_OBJ_NAMEORA_DICT_OBJ_TYPE đều trả lại giá trị cũ của đối tượng cơ sở dữ liệu.Oracle: Làm cách nào để xác định tên MỚI của đối tượng trong trình kích hoạt "SAU KHI GÌ"?

Ví dụ:

CREATE OR REPLACE TRIGGER ADAM_BEFORE_AFTER BEFORE ALTER ON DATABASE 
BEGIN 
    DBMS_OUTPUT.put_line('Before alter: ' || ora_dict_obj_owner || '.' || ora_dict_obj_name || ' (' || ora_dict_obj_type || ')'); 
END; 

CREATE OR REPLACE TRIGGER ADAM_AFTER_ALTER AFTER ALTER ON DATABASE 
BEGIN 
    DBMS_OUTPUT.put_line('After alter: ' || ora_dict_obj_owner || '.' || ora_dict_obj_name || ' (' || ora_dict_obj_type || ')'); 
END; 

Giả sử tôi đổi tên một bảng:

ALTER TABLE USELESS_TABLE9 RENAME TO USELESS_TABLE10 

Các đầu ra cơ sở dữ liệu này:

 
Before alter: DEVELOPER.USELESS_TABLE9 (TABLE) 
After alter: DEVELOPER.USELESS_TABLE9 (TABLE) 

Cập nhật: Thật không may, sản lượng tôi đã trình bày ở trên đã sai. Đầu ra thực sự được tạo bởi kích hoạt BEFORE DDL và kích hoạt AFTER DDL mà tôi đã tạo trước đó, không bởi các kích hoạt BEFORE RENAMEAFTER RENAME. Tôi sẽ tiếp tục điều tra lý do tại sao BEFORE RENAMEAFTER RENAME trigger không bắn ...

Cập nhật: Dường như BEFORE RENAMEAFTER RENAME trigger từ chối bắn, nhưng BEFORE ALTERAFTER ALTER trigger làm. Tôi đã cập nhật câu hỏi cho phù hợp.

Trả lời

6

ALTER RENAME sẽ không kích hoạt trình kích hoạt, RENAME x TO y sẽ.

Đối với câu hỏi của bạn về tên trước và sau đó, tôi nghĩ rằng bạn sẽ phải phân tích các DDL để lấy chúng, như thế:

CREATE OR REPLACE TRIGGER MK_BEFORE_RENAME BEFORE RENAME ON SCHEMA 
DECLARE 
    sql_text ora_name_list_t; 
    v_stmt VARCHAR2(2000); 
    n PLS_INTEGER; 
BEGIN 
    n := ora_sql_txt(sql_text); 
    FOR i IN 1..n LOOP 
    v_stmt := v_stmt || sql_text(i); 
    END LOOP; 

    Dbms_Output.Put_Line('Before: ' || regexp_replace(v_stmt, 'rename[[:space:]]+([a-z0-9_]+)[[:space:]]+to.*', '\1', 1, 1, 'i')); 
    Dbms_Output.Put_Line('After: ' || regexp_replace(v_stmt, 'rename[[:space:]]+.*[[:space:]]+to[[:space:]]+([a-z0-9_]+)', '\1', 1, 1, 'i')); 
END; 

Các biểu thức thông thường chắc chắn có thể được viết rõ ràng hơn, nhưng nó hoạt động :

RENAME 
mktestx 
TO     mktesty; 

Before: mktestx 
After: mktesty 

CẬP NHẬT Để thích ứng với câu hỏi thay đổi của bạn:

CREATE OR REPLACE TRIGGER MK_AFTER_ALTER AFTER ALTER ON SCHEMA 
DECLARE 
    sql_text ora_name_list_t; 
    v_stmt VARCHAR2(2000); 
    n PLS_INTEGER; 
BEGIN 
    n := ora_sql_txt(sql_text); 
    FOR i IN 1..n LOOP 
    v_stmt := v_stmt || sql_text(i); 
    END LOOP; 

    Dbms_Output.Put_Line('Before: ' || regexp_replace(v_stmt, 'alter[[:space:]]+table[[:space:]]+([a-z0-9_]+)[[:space:]]+rename[[:space:]]+to.*', '\1', 1, 1, 'i')); 
    Dbms_Output.Put_Line('After: ' || regexp_replace(v_stmt, 'alter[[:space:]]+table[[:space:]]+.*to[[:space:]]+([a-z0-9_]+)', '\1', 1, 1, 'i')); 
END; 
Các vấn đề liên quan