Am patit un fapt interesant.
Am urmatoarea situatie
Fac insert cu o procedura stocata in 2 tabele cu o tranzactie
BEGIN TRANSACTION
INSERT INTO Tabela1 ....
INSERT INTO Tabela2 ...
COMMIT
IF @ERROR <> 0
ROLLBACK TRANSACTION
La Tabela1 am in trigger AFTER INSERT care insereaza cate un rand in alte 3 tabele
Problema : Totul a functionat perfect dar intr-o zi m-am trezit ca in Tabela1 nu a inserat dar in Tabela2 a inserat. Deasemeni desi in Tabela1 nu a inserat triggerul a functionat si a inserat cate un rand in cele 3 tabele.
E vreo greseala pe undeva si nu o vad eu ?
Sorin Sandu
SET XACT_ABORT ON
GOTO Failure
RETURN
Failure:
ROLLBACK TRAN
In plus trebuie error handling in trigger.
Fara cod e greu de comentat!
Poate e un INSTEAD OF trigger.
Cristi,
Daca ai folosit SET XACT_ABORT ON nu vad de ce ar mai trebui verificat @@ERROR-ul dupa fiecare instructiune. E suficient ori una, ori cealalta. Personal, eu prefer sa tin SET XACT_ABORT OFF si sa verific @@ERROR-ul.
In al doilea rand, de ce trebuie error handling in trigger ? Daca apare o eroare intr-un trigger, se face automat rollback si se termina batch-ul care a declansat trigger-ul.
Pentru detalii, vezi http://www.sommarskog.se/error-handling-I.html
Razvan
SET XACT_ABORT ON transforma majoritatea batch abort errors in transaction abort errors. Chiar la documentul respectiv m-am gandit cand am zis asta http://www.sommarskog.se/error-handling-I.html#XACT_ABORT. Majoritatea inseamna nu chiar toate. Din acest motiv inca mai verific @@ERROR-ul.
De ce error handling in trigger? Desi un trigger trebuie sa fie by design rapid daca business logic-ul din spatele lui e complex atunci eu as face error handling si in trigger. Pe urma in acelasi document poti observa ca aproape toate erorile intr-un trigger determina un rollback automat. Aproape toate dar nu toate!
ssandu:Am patit un fapt interesant.BEGIN TRANSACTIONINSERT INTO Tabela1 ....INSERT INTO Tabela2 ...COMMIT
BEGIN TRANSACTIONINSERT INTO Tabela1 ....INSERT INTO Tabela2 ...COMMIT
Ai patit un fapt banal. Ai comis o transactie fara ca sa te intereseza daca rezultatul ei e consistent sau nu. Daca verifici @@ERROR, trebuie sa-l verifici dupa fiecare statement. Daca primul INSERT a picat (e.g. unique constraint violation), al doilea INSERT va reseta @@ERROR.
Nu e clar din exemplu daca transactia este o subtranzactie intr-o alta tranzactie. Daca nu e, atunci codul e incorect si pentru ca incearca sa faca ROLLBACK dupa ce a facut COMMIT. Daca e, atunci codul risca sa devina incorect la o schimbare minora (e.g. daca caller-ul nu mai porneste o tranzactie explicita). Normal COMMIT-ul se face pe un branch al IF-ului si ROLLBACK pe celalalt.
Numai de bine,~Remus