Как я могу обеспечить выполнение инструкции UPDATE в этом маленьком цикле LOOP внутри транзакции? - PullRequest
0 голосов
/ 30 декабря 2011

У меня есть этот цикл, который обновляет число записей @UpdateBlockSize на каждой итерации:

WHILE 1=1
BEGIN

    UPDATE TOP (@UpdateBlockSize) table1
    SET field1 = nv.value
    FROM table1 i
        INNER JOIN #table2 nv ON nv.id = i.id   
    IF @@ROWCOUNT < @UpdateBlockSize BREAK
END

Вопрос: Как я могу убедиться, что каждая итерация работает в транзакции, так что еслипроисходит сбой, только эта итерация откатывается и LOOP завершается?

Ответы [ 2 ]

1 голос
/ 30 декабря 2011

Любое обновление, которое завершается неудачей, является собственной транзакцией (при условии отсутствия явной внешней транзакции).

Если я вас правильно понимаю ...

  • вы хотите корректно обрабатывать ошибки
  • Вы хотите 10 отдельных транзакций
  • если номер цикла, скажем, 7 не удался, откатить только этот цикл и выйти из цикла
  • Циклы 1-6 остаются совершенными

Итак, попробуйте это

WHILE 1=1
BEGIN
    BEGIN TRY
       UPDATE TOP (@UpdateBlockSize) table1
       SET field1 = nv.value
       FROM table1 i
           INNER JOIN #table2 nv ON nv.id = i.id;
       SET @rc = @@ROWCOUNT
    END TRY
    BEGIN CATCH
       SET @rc = 0;
    END CATCH
    IF @@ROWCOUNT < @UpdateBlockSize BREAK
END

Если вы хотите одну транзакцию для всех циклов, не используйте цикл. Журнал транзакций будет содержать всю информацию об откате для всех циклов, потому что это отдельная транзакция. Если это не сокращенный код, цикл в этом случае не добавляет значения ...

0 голосов
/ 30 декабря 2011

Вы можете проверить переменную @@TRANCOUNT - если она> 0, то у вас есть внешняя транзакция, и, следовательно, - все ваши обновления будут зафиксированы или откатлены одновременно.(Если вы не выбрали фиксацию внешней транзакции - это не рекомендуется).

Если = 0 - тогда каждый из UPDATE вашего цикла выполняется в своей собственной неявной транзакции, поэтому - не нужно беспокоиться, тогда

Попробуйте использовать это:

declare @rc int, @err int 
WHILE 1=1
BEGIN

    UPDATE TOP (@UpdateBlockSize) table1
    SET field1 = nv.value
    FROM table1 i
        INNER JOIN #table2 nv ON nv.id = i.id   

    SELECT @rc = @@ROWCOUNT, @err = @@ERROR
    IF @rc < @UpdateBlockSize OR @err <> 0 BREAK
END
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...