2016-11-04 10 views
0

다른 question 나는 주어진 테이블에서 로그를 유지하는 hist 테이블을 만들려고했습니다. 그 질문에 대한 답변으로 새로운 것을 만들려고 노력했습니다.언제 user_tab_columns가 업데이트 되나요?

create or replace trigger ident_hist_trig after alter on schema 
declare 
    v_table varchar2(30); 
begin 
    select upper(ora_dict_obj_name) into v_table from dual; 
    if (v_table = 'Z_IDENT') then 
     prc_create_hist_tabel('z_ident_hist', 'z_ident'); 
    elsif (v_table = 'D_IDENT') then 
     prc_create_hist_tabel('d_ident_hist', 'd_ident'); 
    elsif (v_table = 'X_IDENT') then 
     prc_create_hist_tabel('x_ident_hist', 'x_ident'); 
    else 
     null; 
    end if; 
end; 
/

프로 시저 prc_create_hist_tabel은 다음과 같다 : 요컨대

create or replace procedure prc_create_hist_tabel(p_naam_hist_tabel in varchar2, p_naam_tabel in varchar2) is 
    cursor c is 
     select 'alter table ' || p_naam_hist_tabel || ' add ' || column_name || ' ' || data_type || case when data_type = 'DATE' then null else '(' || data_length || ')' end lijn 
     from user_tab_columns 
     where TABLE_NAME = upper(p_naam_tabel) 
     and column_name not in (select column_name from user_tab_columns where table_name = upper(p_naam_hist_tabel)); 
    v_dummy number(1); 
    cursor trig is 
     select column_name || ',' kolom, ':old.' || column_name || ',' old 
     from user_tab_columns 
     where table_name = upper(p_naam_tabel); 
    v_trigger_sql varchar2(32767); 
begin 
    begin 
     select 1 into v_dummy 
     from user_tab_columns 
     where TABLE_NAME = upper(p_naam_hist_tabel) 
     group by 1; 
    exception when no_data_found then 
     execute immediate 'create table ' || p_naam_hist_tabel || ' (wijziger varchar2(60) default user, wijzigdatum date default sysdate, constraint pk_' || p_naam_hist_tabel || ' primary key (wijziger, wijzigdatum))'; 
    end; 
    dbms_output.put_line('BBB'); 
    for i in c 
    loop 
     begin 
      dbms_output.put_line(i.lijn); 
      execute immediate i.lijn; 
     exception when others then 
      dbms_output.put_line(i.lijn); 
     end; 
    end loop; 

    v_trigger_sql := 'create or replace trigger ' || p_naam_tabel || '_hist_trig after update on ' || p_naam_tabel || ' for each row begin insert into ' || p_naam_hist_tabel || ' ('; 
    for v_lijn in trig 
    loop 
     v_trigger_sql := v_trigger_sql || v_lijn.kolom; 
    end loop; 
    v_trigger_sql := substr(v_trigger_sql, 1, length(v_trigger_sql) - 1); 
    v_trigger_sql := v_trigger_sql || ') values ('; 
    for v_lijn in trig 
    loop 
     v_trigger_sql := v_trigger_sql || v_lijn.old; 
    end loop; 
    v_trigger_sql := substr(v_trigger_sql, 1, length(v_trigger_sql) - 1); 
    v_trigger_sql := v_trigger_sql || '); end;'; 

    execute immediate v_trigger_sql; 
end; 
/

가 테이블 또는 뷰의 시스템 트리거를 생성 할 수 없으므로

는 I 이런 DDL 트리거를 생성 그 기능이하는 일은 역사표를 유지하는 것입니다. 존재하지 않으면 생성 된 것이고, 존재한다면 새로운 열을 추가합니다. 또한 프로 시저는 갱신 후 히스토리 테이블에 이전 값을 기록하는 새 트리거를 작성합니다.

그러나 x_ident, z_ident 또는 d_ident 테이블 중 하나를 변경하면 커서 c는 아무 것도 반환하지 않습니다.이 커서를 통해 루프 할 때 인쇄물을 확인할 수 있습니다. 테이블을 변경 한 후에 을 선택하면 결과가 나타납니다. 나는 테이블 변경이 실제로 해제되기 전에 프로 시저 prc_create_hist_tabel 실행하고 있다고 생각,

BBB 

d_ident: Table altered. 

그러나 나는 다른 방법으로 주위해야한다 생각 : 나는 테이블 d_ident을 변경에서 얻을

결과이 있습니다 그리고 나는 다음과 같은 것을 얻어야한다고 생각합니다 :

d_ident: Table altered. 

BBB 

도움이 될 것입니다. user_tab_columns에 삽입 할 때 트리거를 만들려고했으나 ORA-25001 : 뷰에서이 트리거 유형을 만들 수 없습니다.

나는 sleep 명령을 시도했지만 그 중 하나도 작동하지 않았습니다.

답변

1

이것은 작동하지 않습니다. 트리거에서 테이블에 추가되는 열을 가져올 수 있다고하더라도 실제로 트리거에서 DDL을 수행하려고하면 트리거에서 DDL이 허용되지 않는다는 오류가 발생합니다.

나는 이것에 접근하는 올바른 방법이 프로모션 스크립트의 일부로 prc_create_hist_tabel을 호출하는 것이 될 것이라고 기대합니다. 합리적인 시스템은 열을 테이블에 추가하지 않습니다. DDL은 소스 제어에 존재하며 테스트 후에 배포되는 프로모션의 일부입니다. 프로모션 스크립트가 기록 표를 수정하지 못하면 테스트 중에 단계를 놓친 것을 알 수 있으며 변경 사항이 프로덕션으로 전송되지 않습니다. 변경 사항이 자동으로 발생하면 변경 제어 기능을 사용하지 않기 때문에 변경 제어 기능을 사용하여 빌드를 수행하는 것이 더 어려워집니다.

이 작업을 자동으로 수행하기로 결정한 경우 트리거는 해당 절차를 호출하는 이 아닌 dbms_job을 사용하여 현실적으로 작업을 제출해야합니다. 이 작업은 DDL 트리거가 커밋 된 트랜잭션 후에 실행됩니다. 이 시점에서 열은 dba_tab_columns에 표시됩니다. 그리고 당신의 직업은 자유롭게 DDL을 할 수 있습니다.