SQL Chinook 数据库触发器:总和为空时的条件

SQL Trigger for Chinook database: condition when sum is null

我正在复习 SQL 并使用 Chinook 数据库进行练习。

可以在此处找到数据模型:https://chinookdatabase.codeplex.com/wikipage?title=Chinook_Schema&referringTitle=Documentation

目标是编写一个触发器,以便在我插入或删除发票行时更新发票 table 中的总计。

CREATE TRIGGER UpdateTotal ON InvoiceLine
AFTER INSERT, DELETE
AS
    UPDATE Invoice
    SET Total = (
        SELECT sum(LineSum) AS InvoiceTotal
        FROM (
            SELECT InvoiceId, (UnitPrice * Quantity) AS LineSum 
            FROM InvoiceLine 
        ) AS WithLineSum
        GROUP BY InvoiceId
        HAVING WithLineSum.InvoiceId = Invoice.InvoiceId
    )

这在我插入和删除发票行记录时效果很好,但删除发票的最后一个发票行时除外。当我这样做时,出现错误:

无法将值 NULL 插入列 'Total'、table 'Chinook.dbo.Invoice';列不允许空值。 更新失败。

所以如果 sum(LineSum) 为空,我基本上需要将它设置为零

我正在努力弄清楚如何构建条件,有人可以帮忙吗?

您应该将子查询包装在 COALESCE 中,基本上

SET Total = COALESCE(...subquery..., 0)

此触发器将更新您不想在每次记录更改时都执行的每张发票。您需要查看插入和删除的伪表以仅更新已更改的发票。

接下来,考虑不使用相关子查询。您需要尽可能快地触发代码,并且使用连接进行更新可能会更快(当然是测试)

最后,您可以对总和使用 coalesce,这样如果它为空,它会将总和更新为零。

您的方法效率低下,因为您每次都更新每张发票,而不是仅更新受操作影响的发票。您需要在触发器中利用特殊的 Inserted and Deleted tables

CREATE TRIGGER UpdateTotal ON InvoiceLine
AFTER INSERT, DELETE
AS
    SET NOCOUNT ON;

    UPDATE Inv
    SET Total = Total + (i.UnitPrice * i.Quantity)
        FROM Inserted i
            INNER JOIN Invoice Inv
                ON i.InvoiceId = Inv.InvoiceId;

    UPDATE Inv
    SET Total = Total - (d.UnitPrice * d.Quantity)
        FROM Deleted d
            INNER JOIN Invoice Inv
                ON d.InvoiceId = Inv.InvoiceId;