Как правило, чтобы убедиться, что удаляемые строки - это те, которые вы суммируете и вставляете, - используйте предложение OUTPUT при удалении.Он может выводить строки, которые были выбраны для удаления.
Вот установка, которая даст нам некоторые транзакции:
USE tempdb;
GO
DROP TABLE IF EXISTS dbo.Transactions;
GO
CREATE TABLE dbo.Transactions
(
TransactionID int NOT NULL IDENTITY(1,1)
CONSTRAINT PK_dbo_Transactions
PRIMARY KEY,
TransactionAmount decimal(18,2) NOT NULL,
TransactionDate date NOT NULL
);
GO
SET NOCOUNT ON;
DECLARE @Counter int = 1;
WHILE @Counter <= 50
BEGIN
INSERT dbo.Transactions
(
TransactionAmount, TransactionDate
)
VALUES (ABS(CHECKSUM(NewId())) % 10 + 1, DATEADD(day, 0 - @Counter * 3, GETDATE()));
SET @Counter += 1;
END;
SELECT * FROM dbo.Transactions;
GO
Теперь следующий код удаляет строки после обрезки и одновременно выводит суммы в переменную таблицы, а затем вставляетобщая строка в таблице транзакций.
DECLARE @CutoffDate date = DATEADD(day, 1, EOMONTH(DATEADD(month, -2, GETDATE())));
DECLARE @TransactionAmounts TABLE
(
TransactionAmount decimal(18,2)
);
BEGIN TRAN;
DELETE dbo.Transactions WITH (TABLOCK)
OUTPUT deleted.TransactionAmount INTO @TransactionAmounts
WHERE TransactionDate < @CutoffDate;
IF EXISTS (SELECT 1 FROM @TransactionAmounts)
BEGIN
INSERT dbo.Transactions (TransactionAmount, TransactionDate)
SELECT SUM(TransactionAmount), DATEADD(day, 1, @CutoffDate)
FROM @TransactionAmounts;
END;
COMMIT;
Обычно я стараюсь по возможности избегать указания блокировок, но, основываясь на вашем предложении, я их добавил.Если бы у вас не было блокировки таблицы, все равно было бы хорошо, но это означало бы, что даже если кто-то добавит новую «старую» строку, пока вы это делаете, она не будет в общем количестве или удалена.Создание сериализуемой транзакции также приведет к результату и будет блокировать меньше, чем блокировка таблицы, если число удаляемых строк было меньше порога эскалации блокировки (по умолчанию 5000).
Надеюсь, это поможет.