У меня есть некоторый код в после того, как вставляют триггер, который может потенциально перестать работать. Такой отказ не крайне важен и не должен откатывать транзакцию. Как я могу захватить ошибку в триггере и иметь остальную часть транзакции, обычно выполняются?
Пример ниже показывает то, что я имею в виду. Триггер намеренно создает состояние ошибки, так что в итоге исходная вставка ("1") никогда не вставляет в таблицу. Попытка/Выгода, казалось, не добивалась цели. Подобный, более старый вопрос о переполнении стека не уступил, ответ за исключением "препятствуют ошибке произойти во-первых" - который не всегда возможен/легок.
Какие-либо другие идеи?
create table test
(
a int not null
);
go
create trigger testTrigger on test
after insert as
begin
insert into test select null;
end;
go
insert into test values ( 1 );
Из-за того, как триггеры реализованы в SQL Server
, все нарушения ограничения в триггерах обдумывают транзакции.
Это то же самое, что делает:
DROP TABLE test
CREATE TABLE test
(
a INT NOT NULL
)
GO
SET XACT_ABORT ON
GO
BEGIN TRANSACTION
BEGIN TRY
INSERT
INTO test
SELECT NULL
END TRY
BEGIN CATCH
INSERT
INTO test
SELECT 1
END CATCH
, который приводит к обреченной транзакции, за исключением того, что нет способа отключить xact_abort
внутри триггера.
SQL Server
также не хватает автономных транзакций.
Это еще одна причина, по которой вы должны поставить всю логику в хранимые процедуры, а не триггеры.
Спусковой механизм не может отказать, и все равно происходит откат транзакции. У вас есть несколько вариантов, чтобы гарантировать, что триггер не сработает.
1 - Вы можете гарантировать, что триггер не даст сбой, дублируя логику проверки ограничений и не пытаясь выполнить операцию, которая нарушит ограничения:
т.е.
INSERT INTO test WHERE val IS NOT NULL
2 - Вы можете отложить потенциально неудачное действие, используя шаблон построения очереди, в которой действия, которые могут или не могут дать сбой, ставятся в очередь, путем вызова таблицы, в которой операция вызова не может дать сбой.
, т.е.
INSERT INTO ACTION_QUEUE (action, parameters) VALUES ('INSERT INTO TEST', val)