Sql Oracle中的绕过变异触发器

Sql Oracle中的绕过变异触发器,sql,oracle,plsql,oracle11g,oracle-apex,Sql,Oracle,Plsql,Oracle11g,Oracle Apex,我有两张桌子;在更新表1(购买的汽车)时,我需要使用特定客户购买的汽车总数更新另一个表 当我尝试它时,我遇到了一个突变的触发器。我曾尝试将其转换为复合触发器,但遇到大量错误、空索引等 明细表: +-----------+---------+--------+------+------+ | customore | car | number | cost | sold | +-----------+---------+--------+------+------+ | josh

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

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

明细表:

+-----------+---------+--------+------+------+
| 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更新销售数据时,行必须汇总并汇总到此汇总表中

汇总表

  +----------+------------+------------+
  | 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的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;

为什么要为此使用
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()
只是为了防止新行没有默认值。

为什么要为此使用
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()
只是为了防止新行没有默认值。

如果您需要更多详细信息,如my code etcA mutating table error(我的代码etcA变异表错误),请告诉我您正在尝试处理导致触发的表。这是不允许的(至少在大多数情况下)。这通常也是设计不佳的标志,但也可能只是不正确的代码。这不能用代码本身来确定。请发布触发器本身。好的,让我重新编辑上面的代码,包括触发器所在的代码。我知道,它会因为我执行的操作而发生变异。。我只是想知道我是如何应对的,因为这个更新消息将针对在那个特定时间更新到y的客户。我本可以做一个after语句触发器,但这会更新汇总表中的每个客户记录。。我不想发生这种事。请帮帮我,伙计。不太喜欢触发器。这不是我的工作。这一点非常重要,我认为你的汇总表的基本设计有缺陷。无论何时存储一个可以计算的值,该值都有很高的“不同步”风险。事实上,我会说这只是时间问题。当您需要报告时,您不应该试图存储“总汽车”和“总成本”,而应该简单地从明细表中计算它们。表的设计应遵循数据规范化原则-第三种标准形式,而不是将1:1映射到某些报表的需要。如果您需要更多详细信息,如我的代码etcA mutating table error表示您正在尝试处理导致触发的表,请告知我。这是不允许的(至少在大多数情况下)。这通常也是设计不佳的标志,但也可能只是不正确的代码。这不能用代码本身来确定。请发布触发器本身。好的,让我重新编辑上面的代码,包括触发器所在的代码。我知道,它会因为我执行的操作而发生变异。。我只是想知道我是如何应对的,因为这个更新消息将针对在那个特定时间更新到y的客户。我本可以做一个after语句触发器,但这会更新汇总表中的每个客户记录。。我不想发生这种事。请帮帮我,伙计。不太喜欢触发器。这不是我的工作。这一点非常重要,我认为你的汇总表的基本设计有缺陷。无论何时存储一个可以计算的值,该值都有很高的“不同步”风险。事实上,我会说这只是时间问题。当您需要报告时,您不应该试图存储“总汽车”和“总成本”,而应该简单地从明细表中计算它们。表的设计应遵循数据规范化原则-第三种标准形式,而不是将1:1映射到某些报告的需要。@gordon linoff,请您在这里分享Old.number和Old.cost的意义是什么?@AnkitBajpai。我想答案解释了这一点。这是以递增的方式更改总数,减去旧值,再加上新值。很抱歉,我仍然没有得到它。在上面的示例中,New.number为1,old.number为5。因此,对于total_汽车而言,最终将变成1而不是6。@AnkitBajpai。差异被添加到现有的值中。@GordonLinoff我今天开始测试代码,我相信正如ankit解释的那样,数学是错误的。例如,如果我的汽车数量目前为5+1-5,那么我最终会得到1——随后,如果有人在之前的任何交易中将y改为n,我最终会得到无法控制的数字。我会在数学上做一点工作——这里也不能避免负数think@gordon林诺夫,你能在这里分享一下Old.number和Old.cost的意义吗?@AnkitBajpai。我想答案解释了这一点。这是以递增的方式更改总数,减去旧值,再加上新值。很抱歉,我仍然没有得到它。在上面的示例中,New.number为1,old.number为5。因此,对于total_汽车而言,最终将变成1而不是6。@AnkitBajpai。差异被添加到现有的值中。@GordonLinoff我今天开始测试代码,我相信正如ankit解释的那样,数学是错误的。例如,如果我的汽车数量目前为5+1-5,那么我最终会得到1——随后,如果有人在之前的任何交易中将y改为n,我最终会得到无法控制的数字。我会做一点数学方面的工作——我想这里也不能避免负数