2016-07-14 2 views
0

상태가 2에서 3으로 변경 될 때 프로 시저를 호출하는 테이블 트리거가 있습니다. 프로 시저가 전체 데이터 그룹 (group_id)이 상태 3에 있는지 확인한 후 일부 작업을 수행합니다.프로 시저 병렬 방지 방지

하지만 이제는 상태 3의 전체 데이터 그룹을 동시에 설정하면 프로 시저가 여러 번 호출되어 여러 번이 동작을 수행한다는 문제가 있습니다. 어떻게 그 사람을 막을 수 있니? 자물쇠와 예를 들어 여기에

내 프로 시저 쿼리입니다 :

 SELECT COUNT(*) 
    INTO nResult 
    FROM ticket 
    WHERE group_id = nGroupId 
    AND statusid BETWEEN 0 AND 2; 

    /* If not all tickets of group in status 3, no action required */ 
    IF nResult != 0 THEN 
     RETURN; 
    END IF; 

그리고 이것은 내 트리거이다, 그 행이 때마다 해고

IF (:NEW.STATUSID = 3 AND :OLD.STATUSID = 2) THEN 
    myprocedure(:NEW.group_id); 
END IF; 
+0

-이 동작을 예상합니다. –

+0

예, 예상 된 동작이지만, 이제는 같은 그룹에 대해 여러 번 병렬 및 일치 작업을 실행하지 않도록 예방이 필요합니다. – ZerOne

답변

1

당신은 아마 행 레벨 트리거가 업데이트; 예를 들면 :

SQL> create or replace trigger update_trigger 
    2 after update on trigger_table 
    3 begin 
    4  dbms_output.put_line('change'); 
    5 end; 
    6/

Trigger created. 

SQL> update trigger_table set status = 1; 
change 

3 rows updated. 

Here 당신이 뭔가 더 찾기 :

SQL> create table trigger_table(status number); 

Table created. 

SQL> insert into trigger_table values (1); 

1 row created. 

SQL> insert into trigger_table values (2); 

1 row created. 

SQL> insert into trigger_table values (3); 

1 row created. 

SQL> create trigger update_trigger 
    2 after update on trigger_table 
    3 for each row /* ROW LEVEL */ 
    4 begin 
    5  dbms_output.put_line('change'); 
    6 end; 
    7/

Trigger created. 

SQL> set serveroutput on 
SQL> update trigger_table set status = 1; 
change 
change 
change 

3 rows updated. 

당신은 모든 업데이트 문 뒤에 발사 테이블 레벨 트리거가 필요합니다. 로 바르게 행 세트가 아니라 하나 하나를 고려, 트리거의 종류, 니콜라스 Krasnov에 의해 관찰

, 당신은하지 :new 또는 :old 값이 있습니다. 요구 사항을 충족시키는 방법은 다음과 같을 수 있지만 까다로운 솔루션이므로 프로덕션 환경에서 사용하기 전에 신중히 확인해야합니다.

트리거를 실행해야하는지 여부를 알기 위해 세마포 테이블을 생성 한 다음 행 수준, 업데이트 전, 테이블 수준 중 하나에서 두 개의 트리거를 사용할 수 있습니다. 행 수준 1은 값을 확인하고 세마포어 테이블을 업데이트하며, 업데이트 후 발생하는 테이블 수준 1은 세마포어를 읽고 필요한 경우 프로 시저를 호출 한 다음 세마포어를 다시 설정합니다. 예를 들어 :

절차는 당신이 행 레벨 트리거를 만든 때문에 2 ~ 3 여러 번 많은 변화가 발생할 때 호출됩니다 귀하의 설명을 바탕으로
SQL> create table trigger_table(status number); 

Table created. 

SQL> insert into trigger_table values (1); 

1 row created. 

SQL> insert into trigger_table values (2); 

1 row created. 

SQL> insert into trigger_table values (3); 

1 row created. 

SQL> create table checkChange (fire varchar2(3)); 

Table created. 

SQL> insert into checkChange values ('NO'); 

1 row created. 

SQL> create or replace trigger before_update_trigger 
    2 before update on trigger_table 
    3 for each row /* ROW LEVEL */ 
    4 begin 
    5  if :new.status = 3 and :old.status = 2 then 
    6   update checkChange set fire = 'YES'; 
    7  end if; 
    8 end; 
    9/

Trigger created. 

SQL> create or replace trigger after_update_trigger 
    2 after update on trigger_table 
    3 declare 
    4 vFire varchar2(3); 
    5 begin 
    6  select fire 
    7  into vFire 
    8  from checkChange; 
    9  if vFire = 'YES' then 
10   dbms_output.put_line('change'); 
11   update checkChange set fire = 'NO'; 
12  end if; 
13 end; 
14/

Trigger created. 

SQL> update trigger_table set status = 2; 

3 rows updated. 

SQL> update trigger_table set status = 3; 
change 

3 rows updated. 

SQL> 
+0

@NicholasKrasnov : 좋은 지적, OP를 고려한 대답을 편집했습니다. 감사합니다. – Aleksej

+0

: 새롭고 오래된 속성이 필요하기 때문에 이것은 내 요구에 맞는 좋은 해결책이 아닙니다. 이 필요에 대한 oracle 구현 잠금이 있습니까? – ZerOne

+0

@ZerOne : 질문에 대한 가능한 해결책을 보여주기 위해 편집되었습니다. – Aleksej