Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/83.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Chinook数据库的SQL触发器:总和为null时的条件_Sql_Sql Server_Triggers_Conditional - Fatal编程技术网

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

Chinook数据库的SQL触发器:总和为null时的条件,sql,sql-server,triggers,conditional,Sql,Sql Server,Triggers,Conditional,我正在复习我的SQL,并使用Chinook数据库进行练习 数据模型可在此处找到: 目标是编写触发器,以便在插入或删除发票行时更新发票表中的合计 CREATE TRIGGER UpdateTotal ON InvoiceLine AFTER INSERT, DELETE AS UPDATE Invoice SET Total = ( SELECT sum(LineSum) AS InvoiceTotal FROM ( SELE

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

数据模型可在此处找到:

目标是编写触发器,以便在插入或删除发票行时更新发票表中的合计

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
    )
当我插入和删除发票行记录时,除了删除发票的最后一个发票行外,这非常有效。当我这样做时,我会得到错误:

无法在“Chinook.dbo.Invoice”表的“Total”列中插入空值;列不允许空值。 更新失败

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


我正在努力弄清楚如何构造条件查询,有人能帮忙吗?

基本上,您应该将子查询封装在一个联合体中

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

每当一条记录发生更改时,此触发器将更新您不希望执行的每个发票。您需要查看插入和删除的伪表,以便仅更新已更改的发票

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


最后,您可以对求和使用coalesce,这样,如果它为null,它将把sume更新为零

您的方法效率低下,因为您每次都在更新每个发票,而不是只更新受操作影响的发票。您需要利用触发器中的特殊功能

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;

@user3689167:我刚刚在我的本地机器上测试了这个,它工作正常。