使用TOTAL()的SQLite查询返回空行,在读取时抛出ConstraintException

本文关键字:读取 ConstraintException TOTAL SQLite 返回 查询 使用 | 更新日期: 2023-09-27 18:12:14

我有一个使用TOTAL()聚合函数的SQL查询:

SELECT
    c.Id,
    c.Name,
    ...
    b.BatchNumber,
    TOTAL(d.OrderedAmount) as TotalOrderedAmount
FROM OrderProducts a
LEFT JOIN WarehouseProducts b ON a.WarehouseProductId = b.Id
...
WHERE a.OrderId = @OrderId
AND (e.Status = @OrderedStatus OR e.Status IS NULL)

(删除多余行)

即使没有找到结果,该查询也至少返回一行,导致每个列都为DBNull(我假设)。当我尝试将此查询的结果加载到DataTable中时,由于null值,我得到了一个ConstraintException。

如果我用0 as TotalOrderedAmount替换TOTAL()行,返回的行数为0,一切正常。

我尝试过使用WHERE a.Id IS NOT NULL,但无论我尝试什么,似乎总是有至少一行返回。

如何修改此查询,以便在没有找到产品时,返回的行数为0,即使使用聚合函数?

使用TOTAL()的SQLite查询返回空行,在读取时抛出ConstraintException

这就是SQL中的聚合查询的工作方式。SQLite文档中是这么说的:

如果SELECT语句是没有GROUP BY子句的聚合查询,则结果集中的每个聚合表达式在整个数据集中求值一次。对于数据集中任意选择的行,结果集中的每个非聚合表达式求值一次。对每个非聚合表达式使用相同的任意选择行。或者,如果数据集包含零行,则针对完全由NULL值组成的行计算每个非聚合表达式。

通过计算结果集中的聚合表达式和非聚合表达式创建的单行结果集数据形成了不使用GROUP by子句的聚合查询的结果。没有GROUP BY子句的聚合查询总是只返回一行数据,即使没有输入数据。

要允许一个空结果,您必须从最外层的查询中删除聚合函数TOTAL。要获取这个值(如果有结果记录),使用子查询:

SELECT
    c.Id,
    c.Name,
    ...
    b.BatchNumber,
    (SELECT TOTAL(d.OrderedAmount)
     FROM SomeTable d
     WHERE d.x = c.y  -- or however d is related to the other tables
    ) AS TotalOrderedAmount
FROM OrderProducts a
JOIN ...              -- without d here
WHERE ...