【问题标题】:Bypass mutating trigger in Oracle绕过Oracle中的变异触发器
【发布时间】:2021-05-21 17:48:09
【问题描述】:

我有两张桌子;在更新表 1(购买的汽车)时,我需要用特定客户购买的汽车总数更新另一个表。

当我尝试它时,我遇到了一个变异触发器。我尝试将其转换为复合触发器,但是遇到了大量错误、空索引等。

detail_table:

+-----------+---------+--------+------+------+
| customore | car     | number | cost | sold |
+-----------+---------+--------+------+------+
| josh      | mustang | 2      | 5    | y    |
| josh      | ford    | 3      | 2    | y    |
| josh      | tesla   | 1      | 3    | n    | -->to update to y
| john      | chevy   | 4      | 1    | y    |
| john      | chevy   | 5      | 2    | y    |
+-----------+---------+--------+------+------+

在从 n 更新到 y 时,行必须汇总并汇总到此汇总表中

summary_table

  +----------+------------+------------+
  | customer | total cars | total cost | 
  +----------+------------+------------+
  | josh     | 5          | 7          | -- > before update  on detail
  +----------+------------+------------+

  +----------+------------+------------+
  | customer | total cars | total cost | 
  +----------+------------+------------+
  | josh     | 6          | 10         | -- > after update on detail
  +----------+------------+------------+

最后,当用户将 josh.total cars 的 n 更新为 y 时,应该变为 1,总成​​本为 10

触发码

CREATE OR REPLACE TRIGGER update_summary_table
    AFTER UPDATE ON detail_table FOR EACH ROW 
    referencing old as old new as new
begin
    
     for i in (select sum(number) s_car, sum(cost) s_cost
               from detail_table 
               where  customer = :new.customer
                 and sold = 'y') loop

update summary_table
set total_cars = i.s_car,
   total_cost = i.s_cost
where customer = :new.customer;

end loop;
end;
end update_summary_table;

【问题讨论】:

  • 如果您需要更多详细信息,例如我的代码等,请告诉我
  • 变异表错误表明您正在尝试处理导致触发器触发的表。这是不允许的(至少在大多数情况下)。它通常也是设计不佳的标志,但也可能只是不正确的代码。这不能用代码本身来确定。请发布触发器本身。
  • 好的,让我重新编辑上面的内容,包括代码
  • 触发器在那里,它会因为我正在执行的动作而发生变异,我知道.. 我只是想知道我是如何解决它的,因为这个更新消息要对客户进行在该特定时间已更新为 y 的人。我本可以做一个 after statement 触发器,但这会更新汇总表中的每个客户记录..这不是我想要发生的事情。请帮助队友。不太热衷于触发器。这不是我的工作。这真的很重要,请
  • 我认为您对汇总表的基本设计存在缺陷。每当您存储一个可以计算的值时,您都会面临该值“不同步”的非常高的风险。事实上,我想说这只是时间问题。与其尝试存储“总汽车”和“总成本”,不如在需要报告时从详细表中计算它们。表格的设计应遵循数据规范化原则 - 第三范式,而不是 1:1 映射到某些报告的需求。

标签: sql oracle plsql oracle11g oracle-apex


【解决方案1】:

为什么要为此使用for 循环?只需使用一次更新:

update summary_table
    set total_cars = coalesce(total_cars, 0) + :new.number - :old.number,
        total_cost = coalesce(total_cost, 0) + :new.cost - :old.cost
    where customer = :new.customer;

这会对摘要进行增量更改,而不是完全重新计算行。

coalesce() 的使用是为了防止新行没有默认值。

【讨论】:

  • @gordon linoff,请您在这里分享一下 Old.number 和 old.cost 的意义是什么?
  • @AnkitBajpai 。 . .我认为答案解释了这一点。这是递增地更改总数,减去旧值并添加新值。
  • 抱歉,我还是没听明白。在上面的例子中,New.number 是 1,old.number 是 5。所以对于 total_cars 这最终会变成 1 而不是 6。
  • @AnkitBajpai 。 . .差值被添加到现有值中。
  • @GordonLinoff 我今天开始测试代码,我相信正如 ankit 解释的那样,数学是关闭的。例如 - 如果我目前有 5 + 1 - 5 的汽车数量,那么我最终会得到 1 - 随后如果有人将之前的任何交易的 y 更改为 n,我最终会得到无法控制的数字。我会稍微研究一下数学——我认为这里也不能避免负数
猜你喜欢
  • 1970-01-01
  • 2011-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多