如果明细表没有记录,如何将主表更新为0值

问题描述 投票:0回答:1

我在 Firebird 3 db 中有 2 个表 - 主表“Docs”用于输出文档,明细表“Recs”用于已售商品。

  • Docs
    的列:doc_id、summa
  • Recs
    的列:id、doc_id、商品、价格、qnt

当客户取消销售时,此记录保留在详细表中,没有删除它,更新触发器更新主表的总计

summa

触发器在最后一条记录保留在输出表中之前运行良好。但是,如果客户取消上次销售并且详细数据集变空,则触发器无法正常工作并显示最后一条记录的

summa
而不是 0。

如何纠正这个触发器?

CREATE OR ALTER TRIGGER RECS_AU FOR Recs
 ACTIVE AFTER UPDATE POSITION 0
 AS
  DECLARE VARIABLE Price DECIMAL(12, 4);
  DECLARE VARIABLE Doc_id INTEGER;
  DECLARE VARIABLE OLD_Price DECIMAL(12, 4);
  BEGIN
   select 
    r.Doc_id,
    coalesce(sum(r.Price*r.Qnt),0)
   from Recs r, Docs d
   where r.Doc_id=new.Doc_id and r.Doc_id=d.Doc_id and r.status<>'deleted'
   group by r.Doc_id
   into :Doc_id, :Summa;
    
     update Docs set
      Docs.Summa=:Summa:
     where Doc_id=:Doc_id;

我知道问题在于编写正确的 SQL,而不是触发器。数据集变空后,它返回空记录集。为什么在数据集为空的情况下合并不起作用并且不将

summa
显示为 0?

SELECT 
    doc_id,
    coalesce(SUM(cast((r.price*r.qnt) as decimal(18,4))),0) as summa
FROM 
    recs r
WHERE 
    doc_id= :doc_id AND status <> 'deleted'
GROUP BY
    doc_id
sql triggers firebird
1个回答
3
投票

正如 Freddie Bell 在评论中提到的,问题在于您正在使用隐式内部联接。这意味着,当

RECS
中的一行没有行时,由于
DOCS
的存在,将不会有行。
您要么需要按照 Freddie 的建议使用显式 

GROUP BY

,仅从

LEFT JOIN
中选择而不加入
RECS
(并省略
DOCS
),或者更简单,只需使用相关子执行更新选择而不先单独执行选择:
GROUP BY

即使 
update DOCS d set d.Summa = ( select coalesce(sum(r.Price*r.Qnt), 0) from RECS r where r.DOC_ID = d.DOC_ID and r.STATUS <> 'deleted' ) where d.DOC_ID = :NEW.DOC_ID

中没有行,这也会起作用,因为缺少

RECS
,当
GROUP BY
中没有匹配行时,这将生成一行。
    

© www.soinside.com 2019 - 2024. All rights reserved.