Цель состоит в том, чтобы предотвратить другой процесс, считывающий баланс, но минимизировать блокировку для других пользователей. Поэтому используйте блокировки типа «таблица как очередь» следующим образом:
SET XACT_ABORT, NOCOUNT ON;
BEGIN TRY
BEGIN TRANSACTION
SELECT @balance = Balance
FROM SomeTable WITH (ROWLOCK, HOLDLOCK, UPDLOCK)
WHERE Account = 'ABC'
--some checks
UPDATE ...
COMMIT TRANSACTION
END TRY
BEGIN CATCH
...
END CATCH
Альтернатива состоит в том, чтобы сделать это за один раз, что более целесообразно, если задействована одна таблица.
CROSS JOIN - это тест на
SET XACT_ABORT, NOCOUNT ON;
BEGIN TRY
--BEGIN TRANSACTION
UPDATE SomeTable WITH (ROWLOCK, HOLDLOCK, UPDLOCK)
SET Balance = Balance - @request
WHERE
ST.Account = 'ABC' AND Balance > @request;
IF @@ROWCOUNT <> 1
RAISERROR ('Not enough in account', 16, 1);
--COMMIT TRANSACTION
END TRY
BEGIN CATCH
...
END CATCH