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;
我正在复习 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;