如何使用更新触发器获取主 table 中的详细信息总和 table 字段
How to get sum of detail table fields in master table with update trigger
Firebird 3.0 数据库中有mastertable'factgad'和detailtable'recgad'
factgad: factgad_k(pr_k)...
recgad: recgad_k(pr_k), factgad_k(fk)...
当我更新 master table 时,我必须获取 table 的详细记录总和,但我无法编写正确的代码。当我尝试更新 master table 时,出现错误:
Error Message:
----------------------------------------
Too many concurrent executions of the same request.
Too many concurrent executions of the same request.
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, co...
---------------------------------------------------
SQLCODE: -693
SQLSTATE: 54001
GDSCODE: 335544663
create or alter trigger factgad_AU FOR factgad
ACTIVE AFTER UPDATE POSITION 0
AS
DECLARE VARIABLE newl DECIMAL(8, 4);
DECLARE VARIABLE oldl DECIMAL(8, 4);
DECLARE VARIABLE newd DECIMAL(8, 4);
DECLARE VARIABLE oldd DECIMAL(8, 4);
DECLARE VARIABLE FACTGAD_K INTEGER;
BEGIN
select
f.factgad_k,
sum(r.fnewl*r.rgad),
sum(r.foldl*r.rgad),
sum(r.fnewd*r.rgad),
sum(r.foldd*r.rgad)
from recgad r, factgad f
where f.factgad_k=new.factgad_k and r.factgad_k=f.factgad_k
group by f.factgad_k
into :factgad_k,:NEWL, :OLDL, :NEWD, :OLDD;
update factgad set
factgad.NEWL=:NEWL,
factgad.OLDL=:OLDL,
factgad.NEWD=:NEWD,
factgad.OLDD=:OLDD
where factgad_k=:FACTGAD_K;
end
触发器有什么问题SQL?我尝试用 where f.factgad_k=43
更改 where 子句 where f.factgad_k=new.factgad_k
但出现相同的错误。重新启动 Firebird 服务没有任何变化。
奇怪的行为,在更新细节 table:
之后用细节总和 table 更新主 table 的更新触发器中出现了同样的错误
CREATE OR ALTER TRIGGER RECGAD_AU FOR RECGAD
ACTIVE AFTER UPDATE POSITION 0
AS
DECLARE VARIABLE NEWL DECIMAL(8, 4);
DECLARE VARIABLE OLDL DECIMAL(8, 4);
DECLARE VARIABLE NEWD DECIMAL(8, 4);
DECLARE VARIABLE OLDD DECIMAL(8, 4);
DECLARE VARIABLE FACTGAD_K INTEGER;
begin
select
r.factgad_k,
sum(r.fnewl*r.rgad),
sum(r.foldl*r.rgad),
sum(r.fnewd*r.rgad),
sum(r.foldd*r.rgad)
from recgad r, factgad f
where r.factgad_k=new.factgad_k and r.factgad_k=f.factgad_k
group by r.factgad_k
into :factgad_k,:NEWL, :OLDL, :NEWD, :OLDD;
update factgad set
factgad.NEWL=:NEWL,
factgad.OLDL=:OLDL,
factgad.NEWD=:NEWD,
factgad.OLDD=:OLDD
where factgad_k=:FACTGAD_K;
end
您正试图在 table FACTGAD
更新时触发的触发器中更新 table FACTGAD
。换句话说,更新触发触发器,哪个更新,哪个触发触发器,等等。这最终会触发错误“同一请求的并发执行过多”.
你不应该在触发器中使用 UPDATE <table>
来触发相同 table 的更新。相反,您应该使用 BEFORE UPDATE
触发器,并将更新后的值分配给 NEW
上下文的列。在 INSERT
或 UPDATE
上的 BEFORE UPDATE
触发器中,对 NEW
上下文的修改将更新要插入或更新的行。然而,在主 table 上触发的触发器中从细节 tables 重新计算值的总和没有多大意义:考虑如果主 table 永远不会更新会发生什么,但添加、删除或更新了详细信息行。
至于你的第二个触发器,我只能猜测你仍然有 FACTGAD
上的触发器,或者你有其他触发器导致 FACTGAD
和 [= 之间的更新周期21=].
顺便说一句,你执行的 select 不需要从 FACTGAD
select,假设你在两者之间有一个外键约束。
TLDR:放弃触发器 factgad_AU
,保留触发器 RECGAD_AU
(但考虑将其设为 AFTER INSERT OR UPDATE
)。
一般来说,master table 中的详细记录总和是不可能可靠的。最好的方法是通过触发细节 table 添加和减去数据,但在负载下它最终会导致更新冲突。您的触发器将在并发环境中以完全错误的值结束。
通常 select 中的聚合计算执行得很好。
Firebird 3.0 数据库中有mastertable'factgad'和detailtable'recgad'
factgad: factgad_k(pr_k)...
recgad: recgad_k(pr_k), factgad_k(fk)...
当我更新 master table 时,我必须获取 table 的详细记录总和,但我无法编写正确的代码。当我尝试更新 master table 时,出现错误:
Error Message:
----------------------------------------
Too many concurrent executions of the same request.
Too many concurrent executions of the same request.
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, col: 3
At trigger 'FACTGAD_AU' line: 21, co...
---------------------------------------------------
SQLCODE: -693
SQLSTATE: 54001
GDSCODE: 335544663
create or alter trigger factgad_AU FOR factgad
ACTIVE AFTER UPDATE POSITION 0
AS
DECLARE VARIABLE newl DECIMAL(8, 4);
DECLARE VARIABLE oldl DECIMAL(8, 4);
DECLARE VARIABLE newd DECIMAL(8, 4);
DECLARE VARIABLE oldd DECIMAL(8, 4);
DECLARE VARIABLE FACTGAD_K INTEGER;
BEGIN
select
f.factgad_k,
sum(r.fnewl*r.rgad),
sum(r.foldl*r.rgad),
sum(r.fnewd*r.rgad),
sum(r.foldd*r.rgad)
from recgad r, factgad f
where f.factgad_k=new.factgad_k and r.factgad_k=f.factgad_k
group by f.factgad_k
into :factgad_k,:NEWL, :OLDL, :NEWD, :OLDD;
update factgad set
factgad.NEWL=:NEWL,
factgad.OLDL=:OLDL,
factgad.NEWD=:NEWD,
factgad.OLDD=:OLDD
where factgad_k=:FACTGAD_K;
end
触发器有什么问题SQL?我尝试用 where f.factgad_k=43
更改 where 子句 where f.factgad_k=new.factgad_k
但出现相同的错误。重新启动 Firebird 服务没有任何变化。
奇怪的行为,在更新细节 table:
之后用细节总和 table 更新主 table 的更新触发器中出现了同样的错误CREATE OR ALTER TRIGGER RECGAD_AU FOR RECGAD
ACTIVE AFTER UPDATE POSITION 0
AS
DECLARE VARIABLE NEWL DECIMAL(8, 4);
DECLARE VARIABLE OLDL DECIMAL(8, 4);
DECLARE VARIABLE NEWD DECIMAL(8, 4);
DECLARE VARIABLE OLDD DECIMAL(8, 4);
DECLARE VARIABLE FACTGAD_K INTEGER;
begin
select
r.factgad_k,
sum(r.fnewl*r.rgad),
sum(r.foldl*r.rgad),
sum(r.fnewd*r.rgad),
sum(r.foldd*r.rgad)
from recgad r, factgad f
where r.factgad_k=new.factgad_k and r.factgad_k=f.factgad_k
group by r.factgad_k
into :factgad_k,:NEWL, :OLDL, :NEWD, :OLDD;
update factgad set
factgad.NEWL=:NEWL,
factgad.OLDL=:OLDL,
factgad.NEWD=:NEWD,
factgad.OLDD=:OLDD
where factgad_k=:FACTGAD_K;
end
您正试图在 table FACTGAD
更新时触发的触发器中更新 table FACTGAD
。换句话说,更新触发触发器,哪个更新,哪个触发触发器,等等。这最终会触发错误“同一请求的并发执行过多”.
你不应该在触发器中使用 UPDATE <table>
来触发相同 table 的更新。相反,您应该使用 BEFORE UPDATE
触发器,并将更新后的值分配给 NEW
上下文的列。在 INSERT
或 UPDATE
上的 BEFORE UPDATE
触发器中,对 NEW
上下文的修改将更新要插入或更新的行。然而,在主 table 上触发的触发器中从细节 tables 重新计算值的总和没有多大意义:考虑如果主 table 永远不会更新会发生什么,但添加、删除或更新了详细信息行。
至于你的第二个触发器,我只能猜测你仍然有 FACTGAD
上的触发器,或者你有其他触发器导致 FACTGAD
和 [= 之间的更新周期21=].
顺便说一句,你执行的 select 不需要从 FACTGAD
select,假设你在两者之间有一个外键约束。
TLDR:放弃触发器 factgad_AU
,保留触发器 RECGAD_AU
(但考虑将其设为 AFTER INSERT OR UPDATE
)。
一般来说,master table 中的详细记录总和是不可能可靠的。最好的方法是通过触发细节 table 添加和减去数据,但在负载下它最终会导致更新冲突。您的触发器将在并发环境中以完全错误的值结束。
通常 select 中的聚合计算执行得很好。