Plsql 更新或插入后更新同一表的PL/SQL触发器

Plsql 更新或插入后更新同一表的PL/SQL触发器,plsql,triggers,procedure,Plsql,Triggers,Procedure,我需要你帮我拿扳机之类的东西。问题是,我有几个id相同的行,还有一个名为status的列。这些行中只有一行可以同时处于“活动”状态。如何在一行更新为“活动”后将所有其他行更改为“非活动”。如注释中所建议的,您应该在存储过程中执行此操作,存储过程可能如下所示: create or replace procedure prc_ActivateThingy(p_Id number) as begin update YourThingy t set t.Active = 'Y' where

我需要你帮我拿扳机之类的东西。问题是,我有几个id相同的行,还有一个名为status的列。这些行中只有一行可以同时处于“活动”状态。如何在一行更新为“活动”后将所有其他行更改为“非活动”。

如注释中所建议的,您应该在存储过程中执行此操作,存储过程可能如下所示:

create or replace procedure prc_ActivateThingy(p_Id number) as
begin
  update YourThingy t
  set t.Active = 'Y'
  where
    t.Id = p_Id;

  dbms_output.put_line(sql%rowcount);

  if sql%rowcount = 0 then
    raise_application_error(-20000, 'No thingy found with id ' || p_Id || '.');
  end if;

  update YourThingy t
  set t.Active = 'N'
  where t.Id <> p_Id;

  dbms_output.put_line(sql%rowcount);
end;
创建或替换过程prc\u ActivateThingy(p\u Id号)作为
开始
更新你的东西
设置t.Active='Y'
哪里
t、 Id=p_Id;
dbms_output.put_行(sql%行计数);
如果sql%rowcount=0,则
引发应用程序错误(-20000,“找不到id为“| | p| u id | |”的内容”);
如果结束;
更新你的东西
设置t.Active='N'
其中t.Id p_Id;
dbms_output.put_行(sql%行计数);
结束;
在触发器中执行同样有效,但如果“触发器魔法”太多,最终应用程序将难以维护。很难预测什么时候触发,而且您可能陷入混乱,难以实现新的业务逻辑或技术重构

因此,为了完整性,这是如何在复合触发器中实现的,尽管再次建议选择上面的选项

create or replace trigger tiuc_YourThingy
for insert or update on YourThingy
compound trigger

  v_Id number;

  before each row is
  begin
    v_Id := null;
    if :new.Active = 'Y' then
      v_Id := :new.Id;
    end if;
  end before each row;

  after statement is
  begin
    if v_Id is not null then
      update YourThingy t
      set
        t.ACTIVE = 'N'
      where
        t.ID <> v_Id;
    end if;
  end after statement;

end;
创建或替换触发器
用于插入或更新您的内容
复合触发器
身份证号码;
在每行之前
开始
v_Id:=null;
如果:new.Active='Y',则
v_Id:=:new.Id;
如果结束;
每行前结束;
声明之后是
开始
如果v_Id不为空,则
更新你的东西
设置
t、 活动='N'
哪里
t、 ID v_ID;
如果结束;
陈述后结束;
结束;

正如注释中所建议的,您应该在存储过程中执行此操作,存储过程可能如下所示:

create or replace procedure prc_ActivateThingy(p_Id number) as
begin
  update YourThingy t
  set t.Active = 'Y'
  where
    t.Id = p_Id;

  dbms_output.put_line(sql%rowcount);

  if sql%rowcount = 0 then
    raise_application_error(-20000, 'No thingy found with id ' || p_Id || '.');
  end if;

  update YourThingy t
  set t.Active = 'N'
  where t.Id <> p_Id;

  dbms_output.put_line(sql%rowcount);
end;
创建或替换过程prc\u ActivateThingy(p\u Id号)作为
开始
更新你的东西
设置t.Active='Y'
哪里
t、 Id=p_Id;
dbms_output.put_行(sql%行计数);
如果sql%rowcount=0,则
引发应用程序错误(-20000,“找不到id为“| | p| u id | |”的内容”);
如果结束;
更新你的东西
设置t.Active='N'
其中t.Id p_Id;
dbms_output.put_行(sql%行计数);
结束;
在触发器中执行同样有效,但如果“触发器魔法”太多,最终应用程序将难以维护。很难预测什么时候触发,而且您可能陷入混乱,难以实现新的业务逻辑或技术重构

因此,为了完整性,这是如何在复合触发器中实现的,尽管再次建议选择上面的选项

create or replace trigger tiuc_YourThingy
for insert or update on YourThingy
compound trigger

  v_Id number;

  before each row is
  begin
    v_Id := null;
    if :new.Active = 'Y' then
      v_Id := :new.Id;
    end if;
  end before each row;

  after statement is
  begin
    if v_Id is not null then
      update YourThingy t
      set
        t.ACTIVE = 'N'
      where
        t.ID <> v_Id;
    end if;
  end after statement;

end;
创建或替换触发器
用于插入或更新您的内容
复合触发器
身份证号码;
在每行之前
开始
v_Id:=null;
如果:new.Active='Y',则
v_Id:=:new.Id;
如果结束;
每行前结束;
声明之后是
开始
如果v_Id不为空,则
更新你的东西
设置
t、 活动='N'
哪里
t、 ID v_ID;
如果结束;
陈述后结束;
结束;

不要在触发器中执行此操作。写一个单独的程序来处理它。你能告诉我怎么做吗?编写过程并在触发器中调用它,或者以其他方式调用它?我建议的是让执行插入的过程调用一个检查和更新所有行的过程,不要在触发器中实现该逻辑,可以在触发器中实现,但将使用复合触发器,这样就可以记住激活的行,并更新
after语句
部分中的所有其他行。但事实上,我同意@SamirAmanov的观点,尽管这在技术上是可能的,但你不应该这么做。十年来我一直在制造这样的触发器,它一直困扰着我的工作和梦想。测试和维护是如此的困难,而且在某个时刻,很难预测一个简单的update语句会做什么。尽量减少触发器的使用,避免使用业务逻辑。不要在触发器中使用。写一个单独的程序来处理它。你能告诉我怎么做吗?编写过程并在触发器中调用它,或者以其他方式调用它?我建议的是让执行插入的过程调用一个检查和更新所有行的过程,不要在触发器中实现该逻辑,可以在触发器中实现,但将使用复合触发器,这样就可以记住激活的行,并更新
after语句
部分中的所有其他行。但事实上,我同意@SamirAmanov的观点,尽管这在技术上是可能的,但你不应该这么做。十年来我一直在制造这样的触发器,它一直困扰着我的工作和梦想。测试和维护是如此的困难,而且在某个时刻,很难预测一个简单的update语句会做什么。尽量减少触发器的使用,避免使用业务逻辑。我已经尝试了两种方法,非常有用,非常感谢。我已经尝试了两种方法,非常有用,非常感谢