Транзакция не откатывается с нарушением PK - PullRequest
2 голосов
/ 06 мая 2020

Насколько мне известно, если мы начнем транзакцию (begin tran / commit tran), она будет полностью выполнена или ничего. Но когда я выполняю код ниже T SQL, первый оператор insert работает, а второй - нет.

Фон: таблица A имеет два столбца (первичный ключ ID, имя varchar), и он уже имел 3 строки данных (ID 1,2,3).

begin tran
    insert into A values (4, 'Tim') -- this works 
    insert into A values (2, 'Tom') -- this doesn't work because it violates the PK constraint
commit tran

select * from A

Вот мой вопрос: поскольку второй оператор insert нарушает ограничение PK и не может быть зафиксирован, я думал, что все внутри этой транзакции должно быть отменено, потому что транзакция должна быть успех или неудача как одно целое. Но на самом деле «Тим» добавлен в «А», а «Том» - нет. Нарушает ли это автоматичность транзакции?

Ответы [ 2 ]

0 голосов
/ 06 мая 2020

Это не то, как транзакции работают на SQL Сервере. Если у вас есть ошибка «завершения оператора», SQL Сервер просто переходит к следующему оператору. Если у вас есть ошибка "пакетного завершения", транзакция прерывается и откатывается.

Теперь я никогда не хочу такого поведения.

Итак, первая строка, которую я пишу в каждом сохраненном процедура:

SET XACT_ABORT ON;

Это сообщает SQL серверу, что ошибки, завершающиеся оператором, должны автоматически переводиться в ошибки, завершающие выполнение пакета. Добавьте этот оператор в начало вашего скрипта, и вы увидите, что теперь он работает должным образом.

0 голосов
/ 06 мая 2020

Это зависит от того, как вы обрабатываете ошибки в транзакции. Если вы их поймаете или проигнорируете (кажется, вы их игнорируете), тогда транзакция будет продолжена и будет зафиксирована.

Любой достойный «менеджер транзакций» языка программирования / фреймворка:

  • Остановит выполнение кода и откатит транзакцию, или
  • Будет doom транзакция, поэтому фиксация никогда не будет выполнена. Вместо этого он будет заменен откатом.

Если вы запустите эти команды в приглашении SQL, вы, вероятно, не используете какой-либо диспетчер транзакций, и поэтому вы можете намеренно игнорировать ошибку и ведёт себя так, будто всё хорошо.

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