Oacle 에서 트리거 를 통 해 각 문장의 영향 총 줄 수 를 기록 합 니 다.

8551 단어 Oacle트리거
Oacle 에서 트리거 를 통 해 각 문장의 영향 총 줄 수 를 기록 합 니 다.
수요 발생:
       업무 시스템 에서 한 단계 의'추출 수'절 차 는 바로 일부 데 이 터 를 다른 서버 에서 본 라 이브 러 리 의 목표 표 로 동기 화 하 는 것 이다.이 과정 은 여러 사람 이 동시에 숫자 를 뽑 아 서로 영향 을 줄 수 있다.테스트 인원 의 반응 이 있 었 다.원래 뽑 은 숫자 는 가끔 이유 없 이 찾 을 수 없 었 고,때로는 중복 행 이 나 왔 다.이 문제 가 발생 한 것 은 틀림없이 추출 논리 문제 와 병행 하 는 문제 일 것 이다!그러나 그들 은 간단 한 요 구 를 제기 했다.데이터 가 언제 삭제 되 었 는 지,언제 삽입 되 었 는 지 알 고 싶다.나 는'표 의 매번 변경'을 감시 해 야 한다.
기술 선택:
     첫째,트리거 를 생각하면 업무 시스템 과 관련 이 없 는 코드 상황 에서 감 시 를 실현 할 수 있다.트리거 는'구문 급 트리거'와'행 급 트리거'로 나 뉜 다.구문 급 은 모든 문 구 를 실행 하기 전에 한 번 씩 실행 하 는 것 입 니 다.만약 에 제 가 모든 SQL 문 구 를 실행 한 후에 표 이름,시간,영향 줄 을 기록 표 에 쓰 면 됩 니 다.
     그러나 문제 가 발생 했 습 니 다.구문 트리거 에서 이 문장의 줄 수 를 얻 을 수 없습니다.sql%rowcount 트리거 에서 오 류 를 보고 하 다.줄 트리거 로 만 줄 수 를 집계 할 수 있 습 니 다!
코드 구조:
전체 모니터링 데이터 줄 의 기능 은 로그 시트,가방,시퀀스 를 포함 합 니 다.
로그 표:목표 표 이름,SQL 실행 시작,종료 시간 을 기록 하고 줄 수 에 영향 을 주 며 데이터 줄 의 일부 열 정 보 를 모니터링 합 니 다.
가방:주로 3 개의 저장 과정 입 니 다.
4.567917.문 구 를 저장 하 는 과정:관련 배열 로 목표 표 이름과 시작 시간 을 기록 하고 다른 값 을 04.567917.줄 작업 저장 과정:관련 배열 목표 표 에 대응 하 는 기록 수 를 1 로 추가 합 니 다4.567917.문 구 는 저장 과정 을 끝 냅 니 다.관련 배열 목표 표 에서 통 계 된 정 보 를 로그 표 에 기록 합 니 다시퀀스:로그 시트 생 성 에 사용 할 메 인 키
코드:
로그 테이블 과 시퀀스:

create table T_CSLOG
(
 n_id   NUMBER not null,
 tblname VARCHAR2(30) not null,
 sj1   DATE,
 sj2   DATE,
 i_hs   NUMBER,
 u_hs   NUMBER,
 d_hs   NUMBER,
 portcode CLOB,
 startrq DATE,
 endrq  DATE,
 bz    VARCHAR2(100),
 n    NUMBER
)
create index IDX_T_CSLOG1 on T_CSLOG (TBLNAME, SJ1, SJ2)
alter table T_CSLOG add constraint PRIKEY_T_CSLOG primary key (N_ID)

  
create sequence SEQ_T_CSLOG
minvalue 1
maxvalue 99999999999
start with 1
increment by 1
cache 20
cycle;

패키지 코드:

-  
create or replace package pck_cslog is
 --          ,           
 type cslog_type is table of t_cslog%rowtype index by t_cslog.tblname%type;
 --           。
 cslog_tbl cslog_type;
 --    。 
 procedure onbegin_cs(v_tblname t_cslog.tblname%type, v_type varchar2);
 --   
 procedure oneachrow_cs(v_tblname t_cslog.tblname%type,
             v_type  varchar2,
             v_code  varchar2 := '',
             v_rq   date := '');
 --    ,      。
 procedure onend_cs(v_tblname t_cslog.tblname%type, v_type varchar2);
end pck_cslog;

--  
create or replace package body pck_cslog is
 --    ,               
 procedure write_cslog(v_tblname t_cslog.tblname%type) is
 begin
  if cslog_tbl.exists(v_tblname) then
   insert into t_cslog values cslog_tbl (v_tblname);
  end if;
 end;
 --    ,            
 procedure clear_cslog(v_tblname t_cslog.tblname%type) is
 begin
  if cslog_tbl.exists(v_tblname) then
   cslog_tbl.delete(v_tblname);
  end if;
 end;
 --  SQL      。 v_type:    ,insert   i, update  u ,delete   d
 procedure onbegin_cs(v_tblname t_cslog.tblname%type, v_type varchar2) is
 begin
   --          ,    。     ,   insert,delete        。
  if not cslog_tbl.exists(v_tblname) then
   cslog_tbl(v_tblname).n_id := seq_t_cslog.nextval;
   cslog_tbl(v_tblname).tblname := v_tblname;
   cslog_tbl(v_tblname).sj1 := sysdate;
   cslog_tbl(v_tblname).sj2 := null;
   cslog_tbl(v_tblname).i_hs := 0;
   cslog_tbl(v_tblname).u_hs := 0;
   cslog_tbl(v_tblname).d_hs := 0;
   cslog_tbl(v_tblname).portcode := ' '; --       
   cslog_tbl(v_tblname).startrq := to_date('9999', 'yyyy');
   cslog_tbl(v_tblname).endrq := to_date('1900', 'yyyy');
   cslog_tbl(v_tblname).n := 0;
  end if;
  cslog_tbl(v_tblname).bz := cslog_tbl(v_tblname).bz || v_type || ',';
  ----       ,  1,      ,     。
  cslog_tbl(v_tblname).n := cslog_tbl(v_tblname).n + 1; 
 end;
 --    。
 procedure oneachrow_cs(v_tblname t_cslog.tblname%type,
             v_type  varchar2,
             v_code  varchar2 := '',
             v_rq   date := '') is
 begin
  if cslog_tbl.exists(v_tblname) then
   --  ,  , 、   
   if v_type = 'i' then
    cslog_tbl(v_tblname).i_hs := cslog_tbl(v_tblname).i_hs + 1;
   elsif v_type = 'u' then
    cslog_tbl(v_tblname).u_hs := cslog_tbl(v_tblname).u_hs + 1;
   elsif v_type = 'd' then
    cslog_tbl(v_tblname).d_hs := cslog_tbl(v_tblname).d_hs + 1;
   end if;
   
   if v_code is not null and
     instr(cslog_tbl(v_tblname).portcode, v_code) = 0 then
    cslog_tbl(v_tblname).portcode := cslog_tbl(v_tblname).portcode || ',' || v_code;
   end if;
  
   if v_rq is not null then
    if v_rq > cslog_tbl(v_tblname).endrq then
     cslog_tbl(v_tblname).endrq := v_rq;
    end if;
    if v_rq < cslog_tbl(v_tblname).startrq then
     cslog_tbl(v_tblname).startrq := v_rq;
    end if;
   end if;
  end if;
 end;
 --    。 
 procedure onend_cs(v_tblname t_cslog.tblname%type, v_type varchar2) is
 begin
  if cslog_tbl.exists(v_tblname) then
   cslog_tbl(v_tblname).bz := cslog_tbl(v_tblname)
                 .bz || '-' || v_type || ',';
   --    ,        。    0 ,      
   cslog_tbl(v_tblname).n := cslog_tbl(v_tblname).n - 1;
   if cslog_tbl(v_tblname).n = 0 then
    cslog_tbl(v_tblname).sj2 := sysdate;
    write_cslog(v_tblname);
    clear_cslog(v_tblname);
   end if;
  end if;
 end;

begin
 null;
end pck_cslog;
바 인 딩 트리거:
상기 코드 가 있 으 면 감시 하고 자 하 는 목표 표 는 세 개의 트리거 를 추가 하고 가방 에 해당 하 는 저장 과정 을 호출 하면 됩 니 다. 내 가 감시 할 거 라 고 가정 해 봐. T_A 의 시계:
     
세 개의 트리거:

--     
create or replace trigger tri_onb_t_a
 before insert or delete or update on t_a
declare
 v_type varchar2(1);
begin
 if inserting then  v_type := 'i'; elsif updating then  v_type := 'u'; elsif deleting then  v_type := 'd'; end if;
 pck_cslog.onbegin_cs('t_a', v_type);
end;

--     
create or replace trigger tri_one_t_a
 after insert or delete or update on t_a
declare
 v_type varchar2(1);
begin
 if inserting then  v_type := 'i'; elsif updating then  v_type := 'u'; elsif deleting then  v_type := 'd'; end if;
 pck_cslog.onend_cs('t_a', v_type);
end;

--     
create or replace trigger tri_onr_t_a
 after insert or delete or update on t_a
 for each row
declare
 v_type varchar2(1);
begin
 if inserting then  v_type := 'i'; elsif updating then  v_type := 'u'; elsif deleting then  v_type := 'd'; end if;
 if v_type = 'i' or v_type = 'u' then
  pck_cslog.oneachrow_cs('t_a', v_type, :new.name); --                  ,           
 elsif v_type = 'd' then
  pck_cslog.oneachrow_cs('t_a', v_type, :old.name);
 end if;
end;
테스트 성과:
트리거 가 만들어 져 서 삽입 삭 제 를 테스트 할 수 있 습 니 다.먼저 100 줄 을 삽입 한 다음 에 몇 줄 을 마음대로 삭제 합 니 다.

declare
 i number;
begin
 for i in 1 .. 100 loop
  insert into t_a values (i, i || 'shenjunjian');
 end loop;
 commit;
 
 delete from t_a  where id > 79;
 delete from t_a  where id < 40;
 commit;
end;

clob 열,삭 제 된 줄 도 표시 할 수 있 습 니 다.

병렬 시 bz 열 에 유사 한 정보 가 있 을 수 있 습 니 다:
i,i,-i,-i  ,이것 은 같은 시간 에 두 개의 문구 가 목표 표를 삽입 하고 있 음 을 나타 낸다.
i,d,-d,-i  삽입 할 때 삭제 문구 가 실행 되 고 있 음 을 나타 낸다.
플랫폼 이 여러 사람 이 사용 할 때 같은 표를 동시에 조작 하 는 상황 을 피 할 수 없습니다.이 열의 값 을 통 해 데이터 뱅 크 의 집행 상황 을 관찰 할 수 있 습 니 다!
읽 어 주 셔 서 감사합니다. 여러분 에 게 도움 이 되 기 를 바 랍 니 다.본 사이트 에 대한 여러분 의 지지 에 감 사 드 립 니 다!

좋은 웹페이지 즐겨찾기