我有2个表在火鸟3数据库-主表"文件"的输出文件和明细表"Recs"销售的商品.

  • Docs列:DOC_ID,SUMA
  • Recs列:ID、DOC_ID、Cargo 、价格、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

推荐答案

正如Freddie Bell在 comments 中提到的,问题是您使用的是隐式内部联接.这意味着,当DOCS中的行在RECS中没有行时,则由于GROUP BY的存在,将不会有行.

您可以像Freddy建议的那样使用显式的LEFT JOIN,只从RECS中 Select 而不加入DOCS(并省略GROUP BY),或者更简单,只使用相关子 Select 执行更新,而不首先单独执行SELECT:

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,则在RECS中没有匹配的行时将生成一行.

Sql相关问答推荐

如何在PostgreSQL中同时为id s列表执行多个update语句?'

如何在case语句中使用条件来计算成对变量

用于平均多个数据并与一个数据点进行比较以判断偏移量的SQL查询

Trino/Presto sq:仅当空值位于组中第一个非空值之后时,才用值替换空值

SQL查询视图与连接?

删除MariaDB数据库中的JSON数据

Select 非重复值并按条件排除行

将日期时间转换为日期格式

带日期函数的复合索引不允许只扫描索引吗?

需要从键-值对数据中提取值

如何在android房间中进行多个加入

具有分组条件的不同计数 (DAX)

将varchar (7)列转换为datetime

函数调用作为插入值语句中的参数

如何根据某个值在where子句中添加某个条件

为数组中的每个元素从表中收集最大整数

连续几天购买的客户

SQL 查询以填充单个列中的所有值

SQL Server Where 条件

Oracle SQL 查询自行运行,但在包装到select count(*) from ()时失败