2010-01-29 11 views
6

Mam pewien kod w wyzwalaczu po wstawieniu, który może się nie powieść. Taka awaria nie jest kluczowa i powinna wycofać transakcję. Jak mogę przechwycić błąd wewnątrz wyzwalacza i zlecić wykonanie reszty transakcji?TSQL powoduje, że wyzwalacz nie działa w trybie cichym.

Poniższy przykład pokazuje, co mam na myśli. Spust celowo tworzy warunek błędu, w wyniku czego oryginalna wstawka ("1") nigdy nie jest wstawiana do tabeli. Try/Catch nie załatwił sprawy. Podobny, older stack overflow question nie dał odpowiedzi, z wyjątkiem "zapobiegania występowaniu błędu w pierwszej kolejności" - co nie zawsze jest możliwe/łatwe.

Jakieś inne pomysły?

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); 
+1

Dlaczego spróbowano/Catch nie działa? – cjk

+0

@ck: ponieważ naruszenia więzów wewnątrz wyzwalaczy skazują transakcje. – Quassnoi

Odpowiedz

2

Wyzwalacz nie może zawieść i nadal ma transakcję do przodu. Masz kilka opcji, aby upewnić się, że wyzwalacz nie zawiedzie.

1 - Można zapewnić, że po nie nie powielając logikę do sprawdzania ograniczeń i nie próbuje wykonać działanie, które naruszają ograniczenia:

tj

INSERT INTO test WHERE val IS NOT NULL 

2 - można odroczyć potencjalnie awarię za pomocą wzoru projektu kolejki, w którym akcje, które mogą, ale nie muszą, przechodzić w kolejce przez umieszczenie w kolejce do tabeli, w której operacja kolejkowania nie może zawieść.

tj

INSERT INTO ACTION_QUEUE (action, parameters) VALUES ('INSERT INTO TEST', val) 
+0

Obawiam się, że to będzie jedyny sposób. To trudne. Zobacz mój komentarz do odpowiedzi Quassnoi poniżej. – BuschnicK

+0

@BuschnicK Making triggers to jedna z bardziej inwazyjnych rzeczy, które możesz zrobić w systemie. Jest to część schematu bazy danych do wymuszania zachowania bazy danych i robisz to w bazie danych innej osoby. Mają swoje miejsce, ale nie sądzę, żeby to było odpowiednie, JEŚLI nie możesz zapewnić, że zachowują się dobrze.Szczerze mówiąc, jeśli używasz wyzwalacza jako jedynego mechanizmu do wysyłania zmian, jeśli wyzwalacz nie działa w trybie cichym, Twoje zmiany nie zostaną wysłane, ale transakcja może się zakończyć i stracisz komunikat "zmiana danych", w jaki sposób w razie potrzeby ponownie zsynchronizuj swoje dane w sposób niezawodny? –

+0

@BuschnicK Byłoby lepiej, gdybyśmy chcieli zmienić sposób przechwytywania danych lub inną technikę ETL, aby porównać zmiany od ostatniej migawki. –

1

Ze względu na sposób wyzwalacze są realizowane w SQL Server wszystkie naruszenia ograniczeń w obrębie wyzwalaczy kara transakcji.

To jest taka sama jak robi:

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 

co skutkuje skazane transakcji, z wyjątkiem, że nie ma sposobu, aby wyłączyć XACT_ABORT wewnątrz wyzwalacza.

SQL Server również nie ma autonomicznych transakcji.

To kolejny powód, dla którego powinieneś umieścić całą logikę w procedurach przechowywanych zamiast wyzwalaczy.

+0

w rzeczywistości nie masz skazanych transakcji, jeśli nie używasz try..catch. –

+0

@Alex: jasne, operacja jest po prostu atomowo anulowana. To było tylko po to, żeby pokazać, co się dzieje. – Quassnoi

+0

W jaki sposób procedury przechowywane pomagają? Pomyślałem, że jeśli jakikolwiek wyzwalacz wywoła procedurę przechowywaną ... Aby podać trochę informacji podstawowych o tym, co próbuję archiwizować tutaj: Mamy dostawcę dostarczonego systemu ERP i chcemy uzyskać aktualne dane to są stoły. Załączamy wyzwalacze do ich tabel, masujemy dane i kopiujemy je do własnej bazy danych. Chcemy zagwarantować, że nasze wyzwalacze nigdy nie zawiodą, ponieważ spowoduje to problemy w oryginalnym systemie ERP. – BuschnicK

0
  1. Można włączyć XACT_ABORT od wewnątrz wyzwalacza (należy zachować ostrożność)
  2. Można mieć spust wywołać procedurę przechowywaną. (Teraz walczę z przeciwnym problemem: chcę, aby transakcja została przerwana, ale ponieważ logika jest wywołana przez SP z wyzwalacza, a nie przez sam wyzwalacz, tak się nie dzieje.)
Powiązane problemy