【问题标题】:Trigger (on mutating tables) updates older data触发器(在变异表上)更新旧数据
【发布时间】:2021-08-30 12:35:51
【问题描述】:

我尝试按行触发器从另一个表更新一个表,但它有问题。

在我添加 PRAGMA AUTONOMOUS_TRANSACTION.. 后触发器工作。但工作方式很奇怪。

Oracle 版本 12c。 我有一个类似的(简化的)代码:



create table w_mutating2 (id number);

insert into  w_mutating1 values (NULL); commit;

create or replace trigger w_mutate_trg1
before insert on w_mutating2 
for each row
declare 
pragma autonomous_transaction;

begin 
    update w_mutating1 set num =  (select max(id) from w_mutating2); 
    commit;

end; 
/

insert into w_mutating2 values (2); 
commit;

select * from w_mutating1;
select * from w_mutating2;

之后我的表 w_mutating1 的值为 NULL。 所以我再次执行它

insert into w_mutating2 values (5); 
commit;

select * from w_mutating1;
select * from w_mutating2;

我的表 w_mutating 有值 => 2 所以我的触发器起作用了..但是一次操作太晚了;) 在我的复杂示例中,我在类似的触发器中使用函数。 当我从命令行使用参数执行函数时,它可以工作。数据没问题。 但是当我从触发器(使用 PRAGMA 自治事务)执行它时,它会如上所述更新我的数据。

有什么办法解决吗?

【问题讨论】:

  • 我不太明白这里有什么问题,你认为什么不起作用。您希望 oracle 在第一次插入时更新 null 吗?我和你一样跑,并且工作正常。
  • pragma autonomous_transaction 表示在单独的事务中执行(就像在另一个会话中完成一样),因此在提交之前它看不到新值。但是为什么不按顺序填充id?那么你就不需要查询表来找到最大值了。
  • 不要那样做。阅读有关处理变异问题的复合触发器
  • @RobertoHernandez 我希望在我插入第一个提交的值后,触发器会发现它作为最大元素并更新我的第二个表,但我仍然有“null”。在我插入下一行( id = 5 )并提交后,我的第二个表将更新为 id = 1 ,而不是我预期的 id = 5
  • 您可能根本不需要触发器或第二个表,只需要一个序列。请使用您尝试使用此解决方案解决的问题来编辑您的问题。 @WilliamRobertson 已经解释了为什么这不会给你任何有用的东西。

标签: sql oracle plsql


【解决方案1】:

这就是它应该如何工作的。因为您的触发器具有pragma autonomous transaction,所以它会生成一个新事务,其中您的更改尚未提交且不可见。因此,当它执行max(id) 时,它看不到它正在发生的未提交更新。

您可以使用compound trigger 解决变异表问题。

你也可以用类似的东西替换你的触发器主体(假设它只有一行并且它只被这个触发器更新):

update w_mutating1 set num = greatest( num, :new.id );

但是没有足够的信息来说明您实际上要解决什么问题,所以这是我能做的最好的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-06
    • 2019-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多