问题描述
Firebird 3.0 数据库中有主表“factgad”和详细表“recgad”。
factgad:factgad_k(pr_k)...
recgad:recgad_k(pr_k)、factgad_k(fk)...
当我更新主表时,我必须得到明细表的记录总和,但我无法编写正确的代码。当我尝试更新主表时,出现错误:
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,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=new.factgad_k
更改 where 子句 where f.factgad_k=43
但出现相同的错误。重新启动 Firebird 服务没有任何变化。
奇怪的行为,更新触发器后出现相同的错误,该触发器在更新明细表后使用明细表的总和更新主表:
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,factgad f
where r.factgad_k=new.factgad_k and r.factgad_k=f.factgad_k
group by r.factgad_k
into :factgad_k,factgad.OLDD=:OLDD
where factgad_k=:FACTGAD_K;
end
解决方法
您正试图在更新表 blocks = int(input('Enter number of blocks:'))
j = 0
i = 0
while i < blocks:
i = i + 1
j = j + I
if j > blocks:
i =i-1
break
height = I
print("The height of the pyramid:",height)
时触发的触发器中更新表 FACTGAD
。换句话说,更新触发触发器,哪个更新,哪个触发触发器等等。这最终会触发错误“同一请求的并发执行过多”。
您不应在触发同一表更新的触发器中使用 FACTGAD
。相反,您应该使用 UPDATE <table>
触发器,并将更新的值分配给 BEFORE UPDATE
上下文的列。在 NEW
或 BEFORE UPDATE
上的 INSERT
触发器中,修改 UPDATE
上下文将更新要插入或更新的行。但是,在主表上触发的触发器中重新计算明细表中的值的总和没有多大意义:考虑如果主表从未更新,但添加、删除或更新明细行会发生什么情况。
至于您的第二个触发器,我只能猜测您在 NEW
上的触发器仍然存在,或者您有其他触发器导致 FACTGAD
和 {{1} 之间的更新循环}.
顺便说一句,您执行的选择不需要从 FACTGAD
中选择,假设您在两者之间有外键约束。
TLDR:删除触发器 RECGAD
,保留触发器 FACTGAD
(但考虑将其设为 factgad_AU
)。
一般来说,主表中的详细记录的总和是不可能可靠的。最好的方法是通过详细表上的触发器添加和减去数据,但在负载下它最终会发生更新冲突。您的触发器将在并发环境中以完全错误的值结束。
通常在 select 中的聚合计算性能足够好。