Исключение хранимой процедуры T-SQL из-за ограничения первичного ключа - PullRequest
0 голосов
/ 08 июня 2018

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

Сначала я вставляю его в tableA, а затем в tableB.

Я немного растерялся, потому что, если вставка в tableA завершится неудачно, я ожидаю, что она выдаст ошибку и не выполнит следующий оператор,Но, похоже, это не так ..

Если возникает исключение, он все равно запускает операторы под ним? ...

  BEGIN
      INSERT INTO TABLEA (Counter) VALUES (1989); -- duplicate error!
      INSERT INTO TABLEB (Counter) VALUES (2010);
  END

Ошибка, которую я получаю:

Нарушение ограничения PRIMARY KEY 'PK_TABLEA'.Невозможно вставить повторяющийся ключ в объект «dbo.TABLEA».Значение дубликата ключа (1989).Оператор был прерван.

Я получаю сообщение об ошибке при вызове этой хранимой процедуры в моем консольном приложении C #.Вот почему я не понимаю, почему это вызывает исключение ... но я продолжаю со следующими утверждениями ...

Ответы [ 2 ]

0 голосов
/ 08 июня 2018

Такое поведение является наследием более ранних версий t-sql и не нарушает обратную совместимость.

Более последовательное и предсказуемое поведение может быть достигнуто путем установки для свойства XACT_ABORT значения

SET XACT_ABORT ON

Очень хорошая статья об этом и других материалах, связанных с обработкой ошибок: http://www.sommarskog.se/error_handling/Part1.html

В соответствующей статье обсуждается это в связи с хранимыми процедурами: В чем преимущество использования "SET"XACT_ABORT ON "в хранимой процедуре?

Сюда также входит совет всегда устанавливать XACT_ABORT ON перед выполнением сценариев tsql, которые состоят из более чем одной команды, или включают транзакцию.

0 голосов
/ 08 июня 2018

В TSQL вы можете использовать TRY / CATCH для этого.При возникновении ошибки последующие операции могут продолжать выполняться и фиксироваться в таблицах.

То, как вы делаете это сейчас:

CREATE TABLE #test1 (ID INT PRIMARY KEY)
GO 
CREATE TABLE #test2 (ID INT PRIMARY KEY)
GO 

BEGIN TRAN;
INSERT INTO #test1 (ID)
VALUES 
(1);

INSERT INTO #test2 (ID)
VALUES 
(1)
;
COMMIT

BEGIN TRAN;
INSERT INTO #test1 (ID)
VALUES 
(1);

INSERT INTO #test2 (ID)
VALUES 
(2);

COMMIT

SELECT * 
FROM #test1
SELECT * 
FROM #test2

С блоком try и catch вы можете предотвратить появление обоих операторов, если произойдет ошибка.

CREATE TABLE #test1 (ID INT PRIMARY KEY)
GO 

CREATE TABLE #test2 (ID INT PRIMARY KEY)
GO 


BEGIN TRAN;

INSERT INTO #test1 (ID)
VALUES 
(1);

INSERT INTO #test2 (ID)
VALUES 
(1)
;

COMMIT


BEGIN TRY
INSERT INTO #test1 (ID)
VALUES 
(1);

INSERT INTO #test2 (ID)
VALUES 
(2)

END TRY

BEGIN CATCH
print('bad things happened')
END CATCH


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