Вопросы о хранимой процедуре обновления строки с общим значением удаленных строк - PullRequest
0 голосов
/ 05 октября 2019

Я хочу удалить строки из таблицы Transactions (которая имеет внешний ключ к моей таблице Customers), а затем обновить 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 не является моей основной компетенцией, я пытаюсь лучше понять этот запрос. В частности, у меня есть несколько вопросов о приведенном выше утверждении UPDATE.

  1. Это обновит все Customers, потому что у меня нет предложения WHERE, верно?
  2. Это правильнообрабатывает случаи, когда у клиента более одной совпадающей строки в таблице @CustomerBalances, верно?
  3. Требуется ли здесь предложение EXISTS?
  4. Вернет ли SUM() 0 или NULL если нет подходящих строк?
  5. Все ли очищено, если у меня нет окончательного оператора DELETE?
  6. Очень важно, чтобы в * 1030 не было внесено никаких изменений. * или Customers стол, пока я делаю это. Имеет ли смысл использовать TABLOCK здесь?
  7. Есть ли какие-либо предложения по поводу общего подхода, который я использую?

1 Ответ

1 голос
/ 05 октября 2019
  1. Это обновит всех клиентов, потому что у меня нет предложения WHERE, верно?

Да. Рассмотрите возможность добавления предложения WHERE, например:

WHERE Id IN (SELECT DISTINCT CustomerId FROM @CustomerBalances)

Это предотвращает обновление остатков, которые не изменились.

Это правильно обрабатывает случаи, когда у клиента есть несколько совпадающих строк в таблице @CustomerBalances, верно?

Да. Потому что вы используете SUM () для их агрегирования.

Требуется ли здесь предложение EXISTS?

Рекомендуется, а не обязательно. Рекомендуется обновлять сальдо только после архивации записей.

Будет ли SUM () возвращать 0 или NULL, если нет совпадающих строк?

Да, это ошибка, из-за которой для сальдо устанавливается значение NULL (или ошибка, если NULLне допускается) для клиентов, у которых не было заархивированных транзакций. Это будет исправлено добавлением предложения WHERE, указанного выше. Если вы по какой-то причине пытаетесь избежать ГДЕ, вы можете исправить это с помощью COALESCE (SUM (Сумма), 0,00)

Все ли вычищено, если у меня нет окончательного оператора DELETE?

Да. Когда процедура завершится, табличная переменная автоматически выйдет из области видимости, так что DELETE не нужен, насколько показывает этот фрагмент.

Крайне важно, чтобы в это время не вносились изменения в таблицу Транзакции или Клиенты. Имеет ли здесь смысл использовать TABLOCK?

Да, но вы должны также указать HOLDLOCK, чтобы сохранить блокировку до завершения транзакции.

Какие-либо предложения по поводу общего подхода, который я использую?

См. Выше, но в целом это выглядит разумным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...