首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >防止并行执行过程

防止并行执行过程
EN

Stack Overflow用户
提问于 2016-07-14 22:30:33
回答 1查看 44关注 0票数 0

我有一个表触发器,当状态从2变为3时,它调用一个过程。该过程检查整个数据组(Group_id)是否处于状态3,然后执行一些操作。

但现在我面临的问题是,当我同时将整个数据组设置为状态3时,该过程会被多次调用,并多次执行此操作。我怎么才能防止他的?例如,使用锁

下面是我的过程查询:

代码语言:javascript
复制
     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;

这是我的触发器:

代码语言:javascript
复制
IF (:NEW.STATUSID = 3 AND :OLD.STATUSID = 2) THEN 
    myprocedure(:NEW.group_id);
END IF;
EN

回答 1

Stack Overflow用户

发布于 2016-07-14 22:46:32

您可能有一个行级触发器,该触发器在每次更新行时触发;例如:

代码语言:javascript
复制
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.

您需要一个表级触发器,在每次update语句之后触发:

代码语言:javascript
复制
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你会发现更多的东西。

正如Nicholas Krasnov正确地观察到的那样,在这种触发器中,考虑到一组行而不是单个行,您没有:new:old值。有一种方法可以满足您的需求,但这是一个棘手的解决方案,在用于生产环境之前,我会仔细检查它。

您可以创建一个信号量表,以了解是否必须触发触发器,然后使用两个触发器,一个在行级,在更新之前,另一个在表级,在更新之后;行级触发器检查值并更新信号量表,而表级1,在更新之后触发,读取信号量,调用您的过程,如果需要,然后重置信号量。例如:

代码语言:javascript
复制
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>
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38376965

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档