Mam Insert
procedurę składowaną, która będzie dostarczać dane Table1
i pobierać Column1
wartość z Table1
oraz wywołać drugą procedurę składowaną, która będzie zasilać Table2.
Ale kiedy wywołuję drugą procedurę składowaną jako:
Exec USPStoredProcName
Otrzymuję następujący błąd:
Liczba transakcji po EXECUTE wskazuje na niezgodną liczbę instrukcji BEGIN i COMMIT. Poprzedni licznik = 1, aktualny licznik = 0.
Przeczytałem odpowiedzi w innych takich pytaniach i nie jestem w stanie stwierdzić, gdzie dokładnie liczba zatwierdzeń jest zepsuta.
sql
sql-server-2012
sqlexception
Vignesh Kumar A.
źródło
źródło
Odpowiedzi:
Jeśli masz blok TRY / CATCH, prawdopodobną przyczyną jest to, że przechwytujesz wyjątek przerwania transakcji i kontynuujesz. W bloku CATCH należy zawsze sprawdzać
XACT_STATE()
i obsługiwać odpowiednie przerwane i niezatwierdzone (skazane) transakcje. Jeśli dzwoniący rozpoczyna transakcję, a calee uderza, powiedzmy, w impas (który przerwał transakcję), w jaki sposób odbiorca ma zamiar poinformować dzwoniącego, że transakcja została przerwana i nie powinna kontynuować „normalnej pracy”? Jedynym wykonalnym sposobem jest ponowne zgłoszenie wyjątku, zmuszając dzwoniącego do obsługi sytuacji. Jeśli po cichu połkniesz przerwaną transakcję, a dzwoniący nadal będzie zakładał, że jest nadal w oryginalnej transakcji, tylko chaos może zapewnić (a błąd, który otrzymasz, jest sposobem, w jaki silnik próbuje się chronić).Polecam zapoznać się z obsługą wyjątków i transakcjami zagnieżdżonymi, które pokazują wzorzec, którego można używać z transakcjami zagnieżdżonymi i wyjątkami:
create procedure [usp_my_procedure_name] as begin set nocount on; declare @trancount int; set @trancount = @@trancount; begin try if @trancount = 0 begin transaction else save transaction usp_my_procedure_name; -- Do the actual work here lbexit: if @trancount = 0 commit; end try begin catch declare @error int, @message varchar(4000), @xstate int; select @error = ERROR_NUMBER(), @message = ERROR_MESSAGE(), @xstate = XACT_STATE(); if @xstate = -1 rollback; if @xstate = 1 and @trancount = 0 rollback if @xstate = 1 and @trancount > 0 rollback transaction usp_my_procedure_name; raiserror ('usp_my_procedure_name: %d: %s', 16, 1, @error, @message) ; end catch end go
źródło
xact_abort on
?if @xstate = -1 rollback;
Patrząc na ten przykład MSDN , powinniśmy nie wycofywania pełną transakcję chyba było nie transakcja zewnętrzna (czyli chyba zrobiliśmybegin tran
). Myślę, że procedura powinna być tylkorollback
wtedy, gdybyśmy rozpoczęli transakcję, która rozwiązałaby problem @ wróbla.Ja też miałem ten problem. Dla mnie powodem było to, że robiłem
return commit
zamiast
commit return
w jednej procedurze składowanej.
źródło
Zwykle dzieje się tak, gdy transakcja jest uruchamiana i albo nie została zatwierdzona, albo nie jest wycofywana.
Jeśli błąd pojawi się w procedurze składowanej, może to zablokować tabele bazy danych, ponieważ transakcja nie została zakończona z powodu błędów w czasie wykonywania przy braku obsługi wyjątków. Możesz użyć obsługi wyjątków, jak poniżej. USTAW XACT_ABORT
SET XACT_ABORT ON SET NoCount ON Begin Try BEGIN TRANSACTION //Insert ,update queries COMMIT End Try Begin Catch ROLLBACK End Catch
Źródło
źródło
Należy pamiętać, że w przypadku korzystania z transakcji zagnieżdżonych operacja ROLLBACK wycofuje wszystkie transakcje zagnieżdżone, w tym tę najbardziej zewnętrzną.
Może to, w przypadku użycia w połączeniu z TRY / CATCH, spowodować błąd, który opisałeś. Zobacz więcej tutaj .
źródło
Może to również wystąpić, jeśli procedura składowana napotka błąd kompilacji po otwarciu transakcji (np. Nie znaleziono tabeli, nieprawidłowa nazwa kolumny).
Okazało się, że muszę użyć 2 procedur składowanych, jednej „roboczej” i jednej opakowującej z try / catch, obie z logiką podobną do tej, którą opisał Remus Rusanu. Przechwytywanie procesu roboczego jest używane do obsługi „normalnych” błędów, a przechwytywanie opakowania do obsługi błędów niepowodzenia kompilacji.
https://msdn.microsoft.com/en-us/library/ms175976.aspx
Błędy, na które nie ma wpływu konstrukcja TRY… CATCH
Mam nadzieję, że pomoże to komuś innemu zaoszczędzić kilka godzin na debugowaniu ...
źródło
W moim przypadku błąd był spowodowany przez plik
RETURN
wewnątrzBEGIN TRANSACTION
. Więc miałem coś takiego:Begin Transaction If (@something = 'foo') Begin --- do some stuff Return End commit
i musi to być:
Begin Transaction If (@something = 'foo') Begin --- do some stuff Rollback Transaction ----- THIS WAS MISSING Return End commit
źródło
Dla mnie po obszernym debugowaniu poprawka była prostym brakującym rzutem; instrukcja w catch po wycofaniu. Bez tego ten brzydki komunikat o błędzie jest tym, co otrzymasz.
begin catch if @@trancount > 0 rollback transaction; throw; --allows capture of useful info when an exception happens within the transaction end catch
źródło
Miałem ten sam komunikat o błędzie, moim błędem było to, że miałem średnik na końcu wiersza COMMIT TRANSACTION
źródło
Raz napotkałem ten błąd po pominięciu tego oświadczenia w mojej transakcji.
COMMIT TRANSACTION [MyTransactionName]
źródło
Moim zdaniem przyjęta odpowiedź to w większości przypadków przesada.
Przyczyną błędu jest często niedopasowanie BEGIN i COMMIT, co wyraźnie wynika z błędu. Oznacza to użycie:
Begin Begin -- your query here End commit
zamiast
Begin Transaction Begin -- your query here End commit
pominięcie transakcji po rozpoczęciu powoduje ten błąd!
źródło
Upewnij się, że nie masz wielu transakcji w tej samej procedurze / zapytaniu, z których jedna lub więcej pozostaje niezatwierdzonych.
W moim przypadku przypadkowo miałem w zapytaniu wyrażenie BEGIN TRAN
źródło
Może to również zależeć od sposobu wywoływania SP z kodu C #. Jeśli SP zwraca jakąś wartość typu tabeli, wywołaj SP za pomocą ExecuteStoreQuery, a jeśli SP nie zwraca żadnej wartości, wywołaj SP za pomocą ExecuteStoreCommand
źródło
Unikaj używania
oświadczenie, gdy używasz
BEGIN TRY ... END TRY BEGIN CATCH ... END CATCH
i
BEGIN, COMMIT & ROLLBACK
instrukcje w procedurach składowanych SQL
źródło
Jeśli masz strukturę kodu podobną do:
SELECT 151 RETURN -151
Następnie użyj:
SELECT 151 ROLLBACK RETURN -151
źródło