Sql 有关使用已删除行的总值更新行的存储过程的问题

Sql 有关使用已删除行的总值更新行的存储过程的问题,sql,sql-server,tsql,Sql,Sql Server,Tsql,我想从具有“我的客户”表外键的交易表中删除行,然后更新Customers.StartingBalance以反映已删除金额的总和 所以我创建了一个存储过程。这是我到目前为止所拥有的 SET NOCOUNT ON; DECLARE @CustomerBalances TABLE ( CustomerId INT, Amount BIGINT ); -- Note: Caller has already begun a transaction DELETE Transaction

我想从具有“我的客户”表外键的交易表中删除行,然后更新Customers.StartingBalance以反映已删除金额的总和

所以我创建了一个存储过程。这是我到目前为止所拥有的

SET NOCOUNT ON;

DECLARE @CustomerBalances TABLE
(
    CustomerId INT,
    Amount BIGINT
);

-- Note: Caller has already begun a transaction

DELETE Transactions WITH (TABLOCK)
OUTPUT deleted.CustomerId, deleted.TotalAmount INTO @CustomerBalances
WHERE [TimeStamp] < @ArchiveDateTime;
IF EXISTS (SELECT 1 FROM @CustomerBalances)
BEGIN
    UPDATE Customers  WITH (TABLOCK)
    SET StartingBalance = StartingBalance +
        (SELECT SUM(Amount) FROM @CustomerBalances cb WHERE Id = cb.CustomerId)
END;
DELETE FROM @CustomerBalances
因为SQL不是我的核心能力,所以我试图更好地理解这个查询。特别是,我对上面的更新声明有一些疑问

这将更新所有客户,因为我没有WHERE子句,对吗? 这可以正确处理客户在@CustomerBlances表中有多个匹配行的情况,对吗? 这里需要EXISTS子句吗? 如果没有匹配行,SUM将返回0或NULL? 如果我没有最终的DELETE语句,所有的东西都被清理了吗? 在执行此操作时,不要对事务或客户表进行任何更改,这一点至关重要。我在这里使用TABLOCK有意义吗? 对我采取的总体方法有什么建议吗? 这将更新所有客户,因为我没有WHERE子句,对吗? 对。考虑添加WHERE子句,如:

WHERE Id IN (SELECT DISTINCT CustomerId FROM @CustomerBalances)
这将防止更新未更改的余额

这可以正确处理客户在@CustomerBlances表中有多个匹配行的情况,对吗? 对。因为您使用SUM来聚合它们

这里需要EXISTS子句吗? 这是推荐的,而不是必需的。这是一个很好的做法,这样您只会在记录存档后尝试更新余额

如果没有匹配行,SUM将返回0或NULL? 是的,这是一个错误,它会导致余额设置为NULL,如果没有存档交易的客户不允许NULL,则会导致余额设置为error。这将通过添加上述WHERE条款来解决。如果您出于某种原因试图避开WHERE,可以使用COALESCESUMAmount 0.00修复它

如果我没有最终的DELETE语句,所有的东西都被清理了吗? 对。当该过程完成时,table变量将自动超出作用域,因此不需要删除,正如本文所示

在执行此操作时,不要对事务或客户表进行任何更改,这一点至关重要。我在这里使用TABLOCK有意义吗? 是的,但是您还应该指定HOLDLOCK以在事务完成之前保持锁

对我采取的总体方法有什么建议吗?
请参见上面的内容,但总的来说这似乎是合理的。

这是microsoft sql server t-sql吗?@DanielButler:两者都有。在我看来,存储似乎是聚合值的内容似乎是一个鲁莽的想法。如果您确实需要一个聚合值,为什么不在SELECT中使用SUM呢?这样,您就不需要返回并更新客户余额的值,而该值是从现有数据中派生出来的。@Larnu:仔细看看。它反映了已删除值的总数。由于您不能对已删除的值求和,并且必须保持真正的平衡,因此需要一个起始平衡列。这不会改变我的观点,@JonathanWood。如果一组行的总和是700,并且删除了一些总和为400的行,那么总和仍然不是700,而是300。没有理由存储聚合值。感谢您抽出时间解决所有问题。特别是,我对HOLDLOCK一点也不熟悉。现在仔细检查一下!