0

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

大师:

master_id(pk) 文档摘要 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
4

1 回答 1

1

问题不在于 delete 语句,问题在于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 beginif (DocSumma=0) then begin在我提议的更改中),不应该是这样if (sum1 = 0) then begin吗?如在,它应该使用更新的总和,而不是旧的总和。

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

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

于 2021-01-14T10:31:45.317 回答