绕过 Oracle 中的变异触发器
Bypass mutating trigger in Oracle
我有两个table;在更新 table 1(购买的汽车)时,我需要用特定客户购买的汽车总数更新另一个 table。
当我尝试时,我遇到了一个变异触发器。我试图将其转换为复合触发器,但是我遇到了大量错误、空索引等。
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 |
+-----------+---------+--------+------+------+
在将 sold 从 n 更新为 y 时,行必须汇总并汇总到此摘要中 table
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
+----------+------------+------------+
最后,当用户将 n 更新为 y 时,josh.total 辆汽车应该变为 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()
是为了防止没有为新行提供默认值。
我有两个table;在更新 table 1(购买的汽车)时,我需要用特定客户购买的汽车总数更新另一个 table。
当我尝试时,我遇到了一个变异触发器。我试图将其转换为复合触发器,但是我遇到了大量错误、空索引等。
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 |
+-----------+---------+--------+------+------+
在将 sold 从 n 更新为 y 时,行必须汇总并汇总到此摘要中 table
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
+----------+------------+------------+
最后,当用户将 n 更新为 y 时,josh.total 辆汽车应该变为 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()
是为了防止没有为新行提供默认值。