2013-02-01 2 views
2

정확하게 동일한 쿼리이지만 여러 테이블에 적용된 많은 트리거를 업데이트하는 작업이 있습니다. FOR 문을 사용하여 이러한 모든 트리거를 업데이트 할 수 있습니까? 실제로해야 할 일은이 모든 트리거에 대해 WHEN 절을 수정하는 것입니다.여러 오라클 트리거 수정

답변

3

이에 대한 dbms_metadat을 사용할 수 있습니다 . 예를 들어

:

declare 
    type arr_tab is table of varchar2(30); 
    v_arr arr_tab; 
    v_trig clob; 
begin 
    dbms_metadata.set_transform_param(DBMS_METADATA.SESSION_TRANSFORM, 
        'SQLTERMINATOR', FALSE); 

    v_arr := arr_tab('TEST_TRIG', 'TEST2_TRIG'); -- change these triggers. 
    for idx in 1..v_arr.count 
    loop 
    v_trig := dbms_metadata.get_ddl('TRIGGER',v_arr(idx), user); 
    execute immediate regexp_replace(regexp_replace(v_trig, 'ALTER TRIGGER.*', ''), 'WHEN ([^\)]*\))', 'WHEN (1=1)', 1, 1, 'mi'); 
    end loop; 
end; 
/

'WHEN ([^\)]*\))', 'WHEN (1=1)' 부분이 (내 경우)와 WHEN 절을 대체 WHEN (1=1).

0

dba_triggers를 사용하여 트리거의 텍스트를 CREATE 또는 INSERT 문으로 추출 할 수 있습니다. 그러나 일부 LONG 데이터 유형 때문에 VARCHAR2로 추출하는 데 문제가 있습니다. 이것은 oracle 사이트의 어딘가에서 사라진 Tom Kytes 패키지를 사용하여 해결할 수 있습니다. 귀하의 필요에 맞게 수정할 수있는 자체 버전이 포함되어 있습니다.

select를 실행하고 when 절을 삽입 한 다음 create 또는 replace 문을 실행하십시오.

이 때문에 trigger_body 긴 데이터 형식을

select 'CREATE OR REPLACE TRIGGER '|| description 
||trigger_body 
from dba_triggers 
where owner = 'Your schema' 

되는하지만 트리거가 4000 개 이상의 문자

가없는 경우이 작업을해야으로 작동하지 않습니다
select 'CREATE OR REPLACE TRIGGER '|| description 
    || ADMIN.LONG_HELP.SUBSTR_OF('select trigger_body from dba_triggers where trigger_name = :0', 
1,4000,'0',dt.trigger_name) 
from dba_triggers dt 
where owner = 'YourSchema'; 


CREATE OR REPLACE PACKAGE ADMIN.LONG_HELP 
    /****************************************************************************** 
     NAME:  LONG_HELP 
     PURPOSE: Read fields of type long. (commonly found in data dictionary) 

     REVISIONS: 
     Ver  Date  Author   Description 
     --------- ---------- --------------- ------------------------------------ 
     1.0  10/27/2011    1. Created this package. based on Tom Kyte's column here 
     http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:839298816582 
     note that it only retrieves the first 4000 characters of any LONG column 
     USAGE in a WHERE 
     INSTR(
     ADMIN.LONG_HELP.SUBSTR_OF('SELECT text from all_views where view_name =:o ', 
     1,4000,'o',m2.obj_name),m1.FK_ID) > 0 

    ******************************************************************************/ 

    --AUTHID CURRENT_USER 
    --removed to get around ORA-29470: Effective userid or roles are not the same as when cursor was parsed 
    --restrict usage to admin schema for Oracle 11g 

AS 
    FUNCTION substr_of (p_query IN VARCHAR2, 
         p_from IN NUMBER, 
         p_for  IN NUMBER, 
         p_name1 IN VARCHAR2 DEFAULT NULL , 
         p_bind1 IN VARCHAR2 DEFAULT NULL , 
         p_name2 IN VARCHAR2 DEFAULT NULL , 
         p_bind2 IN VARCHAR2 DEFAULT NULL , 
         p_name3 IN VARCHAR2 DEFAULT NULL , 
         p_bind3 IN VARCHAR2 DEFAULT NULL , 
         p_name4 IN VARCHAR2 DEFAULT NULL , 
         p_bind4 IN VARCHAR2 DEFAULT NULL) 
     RETURN VARCHAR2; 
END LONG_HELP; 
/
CREATE OR REPLACE PACKAGE BODY ADMIN.LONG_HELP 
AS 
    g_cursor NUMBER := DBMS_SQL.open_cursor; 
    g_query VARCHAR2 (32765); 


    PROCEDURE bind_variable (p_name IN VARCHAR2, p_value IN VARCHAR2) 
    IS 
    BEGIN 
     IF (p_name IS NOT NULL) 
     THEN 
     DBMS_SQL.bind_variable (g_cursor, p_name, p_value); 
     END IF; 
    END BIND_VARIABLE; 



    FUNCTION substr_of (p_query IN VARCHAR2, 
         p_from IN NUMBER, 
         p_for  IN NUMBER, 
         p_name1 IN VARCHAR2 DEFAULT NULL , 
         p_bind1 IN VARCHAR2 DEFAULT NULL , 
         p_name2 IN VARCHAR2 DEFAULT NULL , 
         p_bind2 IN VARCHAR2 DEFAULT NULL , 
         p_name3 IN VARCHAR2 DEFAULT NULL , 
         p_bind3 IN VARCHAR2 DEFAULT NULL , 
         p_name4 IN VARCHAR2 DEFAULT NULL , 
         p_bind4 IN VARCHAR2 DEFAULT NULL) 
     RETURN VARCHAR2 
    AS 
    /****************************************************************************** 
    NAME:  LONG_HELP.SUBSTR_OF 
    PURPOSE: CONVERT long data fields into VARCHAR2 
    WHOSE DATA IS CHANGED: none 
    WHAT USES THIS: 
    WHERE ARE THE RESOURCES NEEDED: 

******************************************************************************/ 
     l_buffer  VARCHAR2 (4000); 
     l_buffer_len NUMBER; 
    BEGIN 
     IF (NVL (p_from, 0) <= 0) 
     THEN 
     raise_application_error (-20002, 
            'From must be >= 1 (positive numbers)'); 
     END IF; 

     IF (NVL (p_for, 0) NOT BETWEEN 1 AND 4000) 
     THEN 
     raise_application_error (-20003, 'For must be between 1 and 4000'); 
     END IF; 


     IF (p_query <> g_query OR g_query IS NULL) 
     THEN 
     IF (UPPER (TRIM (NVL (p_query, 'x'))) NOT LIKE 'SELECT%') 
     THEN 
      raise_application_error (-20001, 'This must be a select only'); 
     END IF; 

     DBMS_SQL.parse (g_cursor, p_query, DBMS_SQL.native); 
     g_query := p_query; 
     END IF; 

     bind_variable (p_name1, p_bind1); 
     bind_variable (p_name2, p_bind2); 
     bind_variable (p_name3, p_bind3); 
     bind_variable (p_name4, p_bind4); 

     DBMS_SQL.define_column_long (g_cursor, 1); 

     IF (DBMS_SQL.execute_and_fetch (g_cursor) > 0) 
     THEN 
     DBMS_SQL.column_value_long (g_cursor, 
            1, 
            p_for, 
            p_from - 1, 
            l_buffer, 
            l_buffer_len); 
     END IF; 

     RETURN l_buffer; 
    END substr_of; 
END LONG_HELP; 
/