删除明细表中的记录后更新主表的过程出错

问题描述

在 Interbase 2009 db 中,我有主表和明细表(Tmaster、Tdetails)。

老师:

master_id(pk) DocSumma DocSummaDol

详细信息:

det_id master_id(fk) 价格1,价格2 qnt

在我删除/更新子表(Tdetails)中的记录后,必须更新主表(Tmaster)中的总和。

我有两个问题:

  1. 如果过程包含这个 if 子句:
if (m.DocSumma=0) then begin delete from Tmaster m where m.master_id=:master_id; end

它返回这个错误

列不属于引用的表。动态 sql 错误sql 错误代码 = -206。列未知。

  1. 如果没有 if 子句,我有第二个问题:程序运行非常慢。它会在 13 小时后结束 :)

有时在 IBExpert 中我会收到此错误

发生算术溢出或被零除。算术 异常、数字溢出或字符串截断。 sqlCODE:-802 GDSCODE:335544321

我的 Psql 代码有什么问题?

alter procedure sp_recalculate_summa
as
    declare variable master_id integer;
    declare variable det_id integer;
    declare variable sum1 decimal(8,4) ;
    declare variable sum2 decimal(8,4) ;
    begin
        for  select m.master_id
        from Tmaster m
        into :master_id
        do begin
            sum1=0;
            sum2=0;
            for select det_id,sum(d.price1*d.qnt)as summa1,sum(d.price2*d.qnt)as summa2
            from Tdetails d,Tmaster m
            where d.det_id=:master_id
            group by det_id
            into :det_id,:sum1,:sum2
            do
                if (m.DocSumma=0) then begin 
                    delete from Tmaster m where m.master_id=:master_id; 
                end 
                Else begin
                    update Tmaster set DocSumma=:sum1 where master_id=:master_id;
                    update Tmaster set DocSummaDol=:sum2 where master_id=:master_id;
                end
        end
    end

解决方法

问题不在于删除语句,问题在于if (m.DocSumma=0) then begin。您不能在 PSQL 块中引用这样的表。您需要将该列值显式分配给局部变量。

例如,类似于:

alter procedure sp_recalculate_summa
as
    declare variable master_id integer;
    declare variable DocSumma decimal(8,4);
    declare variable det_id integer;
    declare variable sum1 decimal(8,4) ;
    declare variable sum2 decimal(8,4) ;
    begin
        for  select m.master_id,m.DocSumma
        from Tmaster m
        into master_id,DocSumma
        do begin
            sum1=0;
            sum2=0;
            for select det_id,sum(d.price1*d.qnt)as summa1,sum(d.price2*d.qnt)as summa2
            from Tdetails d,Tmaster m
            where d.det_id=:master_id
            group by det_id
            into det_id,sum1,sum2
            do
                if (DocSumma=0) then begin 
                -- etc..
                end
        end
    end

补充说明:

  • 我质疑条件if (m.DocSumma=0) then begin(我提议的更改中的if (DocSumma=0) then begin)的正确性,这不应该是if (sum1 = 0) then begin吗?如在,它应该使用更新的总和,而不是旧的总和。

  • 另外,你为什么要更新 TMASTER 两次?使用单个更新会更有效:

    update Tmaster set DocSumma=:sum1,DocSummaDol=:sum2 where master_id=:master_id;
    
  • 其中一些更改最好通过 TDETAILSTMASTER 上的触发器完成,而不是使用延迟的显式重新计算。