2013-02-22 10 views
7

Utworzono procedurę składowaną, która uruchamia szereg poleceń służących do modyfikacji danych. Chcę tylko dokonać transakcji, jeśli wszystko się powiedzie. Robię to za pomocą bloku try-catch w sposób widoczny poniżej (gdzie mój blok CATCH w prawdziwych używa RAISERROR wrócić komunikaty o błędach):SQL: Try/Catch nie przechwytuje błędu podczas próby uzyskania dostępu do tabeli, której nie może znaleźć

BEGIN TRY 
    BEGIN TRANSACTION 
    UPDATE Table1 SET MyVarcharColumn = 'test' 
    UPDATE Table2 SET MyBitColumn = 1 
    UPDATE Table3 SET MyIntColumn = 42 
    COMMIT TRANSACTION 
END TRY 
CATCH 
    ROLLBACK TRANSACTION 
END CATCH 

To działa tak, jak chcemy. Jeśli, na przykład, ustawię MyBitColumn na "b" zamiast 1, błąd zostanie przechwycony, sterowanie przejdzie do CATCH, a transakcja nie zostanie zatwierdzona.

Jednym z problemów, które zauważyłem jest to, że jeśli, powiedzmy, Tabela 3 nie istnieje w bazie danych, to powoduje błąd (nieważna nazwa obiektu), ale blok CATCH nigdy nie jest wykonywany, a transakcja pozostaje otwarta.

Chcę poradzić sobie z tym, aby zająć się jakąkolwiek (zdalną) możliwością modyfikacji bazy danych (lub dzieje się tak, gdy procedura składowana jest poprawnie dodawana, ale jedna z tabel nie jest).

Jak obsługiwać te przypadki błędów?

-Dziękuję za pomoc.

Odpowiedz

9

Na początku skryptu użyć SET XACT_ABORT

SET XACT_ABORT ON 

Kiedy SET XACT_ABORT jest włączony, jeśli oświadczenie Transact-SQL podnosi błąd czasu , cała transakcja jest zakończona i wycofana.

nie sądzę, że będzie to możliwe:

następujące rodzaje błędów nie są obsługiwane przez blok CATCH gdy występują one na tym samym poziomie wykonania jako try ... catch skonstruować:

  • Błędy kompilacji, takie jak błędy składniowe, które uniemożliwiają uruchomienie wsadu.

  • Błędy występujące podczas rekompilacji na poziomie instrukcji, , takie jak błędy rozpoznawania nazw obiektów, które występują po kompilacji z powodu odroczonego rozpoznawania nazw.

Ref.

Poniższy przykład pokazuje, jak błąd rozdzielczości nazwa obiektu generowane przez SELECT nie zostanie złapany przez TRY ... CATCH konstrukt, ale zostaje złapany przez blok CATCH, kiedy ta sama SELECT oświadczenie jest wykonywany Wewnątrz procedura składowana.

USE AdventureWorks2012; 
GO 

BEGIN TRY 
    -- Table does not exist; object name resolution 
    -- error not caught. 
    SELECT * FROM NonexistentTable; 
END TRY 
BEGIN CATCH 
    SELECT 
     ERROR_NUMBER() AS ErrorNumber 
     ,ERROR_MESSAGE() AS ErrorMessage; 
END CATCH 

Błąd nie został złapany i kontrola przechodzi z TRY ... CATCH skonstruować do kolejnego wyższego poziomu.

+0

Dziękuję. Przydaje się ustawienie, które powoduje wycofanie transakcji. Jednak nadal nie wykonuje tego, co znajduje się w bloku CATCH po błędzie. Działa to dla mojej aplikacji (ponieważ błąd zostanie przekazany w górę w każdym razie), ale jeśli ktoś próbowałby upewnić się, że blok CATCH jest wykonywany z innych powodów, nie zrobiłby tego. – Luke

+0

Ah, rozumiem, oni nie są po prostu złapani za tego rodzaju błędy w tym przypadku. Dzięki! – Luke

-1
EXECUTE ('SELECT * FROM NonexistentTable'); 
Powiązane problemy