Sql Oracle中的绕过变异触发器
我有两张桌子;在更新表1(购买的汽车)时,我需要使用特定客户购买的汽车总数更新另一个表 当我尝试它时,我遇到了一个突变的触发器。我曾尝试将其转换为复合触发器,但遇到大量错误、空索引等 明细表:Sql Oracle中的绕过变异触发器,sql,oracle,plsql,oracle11g,oracle-apex,Sql,Oracle,Plsql,Oracle11g,Oracle Apex,我有两张桌子;在更新表1(购买的汽车)时,我需要使用特定客户购买的汽车总数更新另一个表 当我尝试它时,我遇到了一个突变的触发器。我曾尝试将其转换为复合触发器,但遇到大量错误、空索引等 明细表: +-----------+---------+--------+------+------+ | customore | car | number | cost | sold | +-----------+---------+--------+------+------+ | josh
+-----------+---------+--------+------+------+
| 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,我最终会得到无法控制的数字。我会做一点数学方面的工作——我想这里也不能避免负数