Theo mặc định, hầu hết thời gian, Giao dịch không được tự động khôi phục / hủy khi xảy ra lỗi. Đây thường không phải là vấn đề miễn là bạn có cách xử lý lỗi thích hợp và ROLLBACKtự gọi cho mình. Tuy nhiên, đôi khi mọi thứ trở nên phức tạp, chẳng hạn như trong trường hợp xảy ra lỗi hủy bỏ hàng loạt hoặc khi sử dụng OPENQUERY(hoặc Máy chủ được liên kết nói chung) và xảy ra lỗi trên hệ thống từ xa. Mặc dù hầu hết các lỗi có thể bị mắc bẫy bằng cách sử dụng TRY...CATCH, có hai lỗi không thể bị mắc kẹt theo cách đó (mặc dù không thể nhớ lỗi nào tại thời điểm này - nghiên cứu). Trong những trường hợp này, bạn phải sử dụng SET XACT_ABORT ONđể khôi phục đúng Giao dịch.
SET XACT_ABORT ON khiến SQL Server lập tức quay lại bất kỳ Giao dịch nào (nếu một giao dịch đang hoạt động) và hủy bỏ lô nếu có lỗi xảy ra. Cài đặt này tồn tại trước SQL Server 2005, đã giới thiệu TRY...CATCHcấu trúc. Đối với hầu hết các phần, TRY...CATCHxử lý hầu hết các tình huống và do đó chủ yếu là lỗi thời XACT_ABORT ON. Tuy nhiên, khi sử dụng OPENQUERY(và có thể là một kịch bản khác mà tôi không thể nhớ vào lúc này), thì bạn vẫn sẽ cần sử dụng SET XACT_ABORT ON;.
Bạn phải luôn có cách xử lý lỗi thích hợp, đặc biệt là khi sử dụng Giao dịch. Cấu TRY...CATCHtrúc, được giới thiệu trong SQL Server 2005, cung cấp một phương thức xử lý gần như tất cả các tình huống, một cải tiến đáng hoan nghênh so với thử nghiệm @@ERRORsau mỗi câu lệnh, điều này không giúp ích nhiều cho các lỗi hủy bỏ hàng loạt.
TRY...CATCHgiới thiệu một "trạng thái" mới, tuy nhiên. Khi không sử dụng TRY...CATCHcấu trúc, nếu bạn có Giao dịch đang hoạt động và xảy ra lỗi, thì có một số đường dẫn có thể được thực hiện:
XACT_ABORT OFFvà lỗi hủy bỏ câu lệnh: Giao dịch vẫn hoạt động và quá trình xử lý tiếp tục với câu lệnh tiếp theo , nếu có.
XACT_ABORT OFFvà hầu hết các lỗi hủy bỏ hàng loạt: Giao dịch vẫn hoạt động và quá trình xử lý tiếp tục với đợt tiếp theo , nếu có.
XACT_ABORT OFFvà một số lỗi hủy bỏ hàng loạt nhất định: Giao dịch được khôi phục và xử lý tiếp tục với đợt tiếp theo , nếu có.
XACT_ABORT ONvà bất kỳ lỗi nào : Giao dịch được khôi phục và xử lý tiếp tục với đợt tiếp theo , nếu có.
TUY NHIÊN, khi sử dụng TRY...CATCH, các lỗi hủy bỏ hàng loạt không hủy bỏ lô mà thay vào đó chuyển điều khiển sang CATCHkhối. Khi XACT_ABORTlà OFF, các giao dịch vẫn sẽ là hoạt động đại đa số thời điểm đó, và bạn sẽ cần phải COMMIT, hoặc có khả năng nhất, ROLLBACK. Nhưng khi gặp phải một số lỗi hàng loạt hủy (chẳng hạn như với OPENQUERY), hoặc khi XACT_ABORTlà ON, các giao dịch sẽ được trong một trạng thái mới, "uncommitable". Ở trạng thái này, bạn không thể COMMIT, bạn cũng không thể thực hiện bất kỳ hoạt động DML nào. Tất cả những gì bạn có thể làm là ROLLBACKvà SELECTtuyên bố. Tuy nhiên, trong trạng thái "không thể khắc phục" này, Giao dịch đã được khôi phục khi xảy ra lỗi và việc ban hành ROLLBACKchỉ là một hình thức, nhưng phải thực hiện.
Một hàm, XACT_STATE , có thể được sử dụng để xác định xem Giao dịch có hoạt động, không có tác dụng hay không tồn tại. Nên kiểm tra (ít nhất là một số, ít nhất) để kiểm tra chức năng này trong CATCHkhối để xác định xem kết quả có -1(nghĩa là không có ích) thay vì kiểm tra nếu @@TRANCOUNT > 0. Nhưng với XACT_ABORT ON, đó phải là trạng thái duy nhất có thể tồn tại, vì vậy có vẻ như việc kiểm tra @@TRANCOUNT > 0và XACT_STATE() <> 0tương đương. Mặt khác, khi XACT_ABORTlà OFFvà có một giao dịch tích cực, sau đó nó có thể có tình trạng một trong hai 1hoặc -1trong CATCHkhối, cho phép khả năng phát hành COMMITthay vì ROLLBACK(mặc dù, tôi không thể nghĩ ra một trường hợp khi một người nào đó muốnCOMMITnếu Giao dịch được cam kết). Có thể tìm thấy thêm thông tin và nghiên cứu về việc sử dụng XACT_STATE()trong một CATCHkhối với XACT_ABORT ONcâu trả lời của tôi cho câu hỏi DBA.SE sau: Trong trường hợp nào giao dịch có thể được thực hiện từ bên trong khối CATCH khi XACT_ABORT được đặt thành BẬT? . Xin lưu ý rằng có một lỗi nhỏ XACT_STATE()khiến nó trả về sai 1trong một số trường hợp nhất định: XACT_STATE () trả về 1 khi được sử dụng trong CHỌN với một số biến hệ thống nhưng không có mệnh đề TỪ
spNewBilling3ném lỗi, nhưng bạn không muốn quay lạispNewBilling2hoặcspNewBilling1sau đó chỉ cần xóa[begin|rollback|commit] transaction createSavebillinginvoicekhỏispSavesomename.