Tóm tắt về TL; DR / Điều hành: Về phần này của Câu hỏi:
Tôi không thấy trong trường hợp nào quyền kiểm soát có thể được chuyển vào bên trong CATCHvới một giao dịch có thể được cam kết khi XACT_ABORTđược đặt thànhON .
Bây giờ tôi đã thực hiện khá nhiều thử nghiệm về điều này và tôi không thể tìm thấy bất kỳ trường hợp nào XACT_STATE()trả về 1bên trong một CATCHkhối khi @@TRANCOUNT > 0 và thuộc tính phiên XACT_ABORTlà ON. Và trên thực tế, theo trang MSDN hiện tại cho SET XACT_ABORT :
Khi SET XACT_ABORT BẬT, nếu câu lệnh Transact-SQL xuất hiện lỗi thời gian chạy, toàn bộ giao dịch bị chấm dứt và được khôi phục.
Tuyên bố đó dường như phù hợp với suy đoán của bạn và phát hiện của tôi.
Bài viết về MSDN SET XACT_ABORTcó một ví dụ khi một số câu lệnh bên trong giao dịch thực hiện thành công và một số lỗi khi XACT_ABORTđược đặt thànhOFF
Đúng, nhưng các câu lệnh trong ví dụ đó không nằm trong một TRYkhối. Những tuyên bố tương tự trong một TRYkhối vẫn sẽ ngăn chặn thực hiện đối với bất kỳ báo cáo sau khi một trong đó gây ra lỗi, nhưng giả sử rằng XACT_ABORTlà OFF, khi kiểm soát được thông qua vào CATCHkhối các giao dịch vẫn còn chất có giá trị ở chỗ tất cả các thay đổi trước đã xảy ra mà không có lỗi và có thể được cam kết, nếu đó là mong muốn, hoặc chúng có thể được khôi phục. Mặt khác, nếu XACT_ABORTlà ONsau đó bất kỳ thay đổi trước sẽ được tự động cuộn lại, và sau đó bạn có sự lựa chọn một trong hai: a) vấn đề mộtROLLBACKmà chủ yếu là chỉ là một sự chấp nhận của tình hình kể từ khi giao dịch đã được cuộn lại trừ đi đặt @@TRANCOUNTđể 0, hoặc b) nhận được một lỗi. Không có nhiều sự lựa chọn, phải không?
Một chi tiết quan trọng có thể có cho câu đố này không rõ ràng trong tài liệu đó SET XACT_ABORTlà thuộc tính phiên này và mã ví dụ đó, đã xuất hiện từ SQL Server 2000 (tài liệu gần như giống hệt nhau giữa các phiên bản), trước TRY...CATCHcấu trúc giới thiệu trong SQL server 2005. nhìn vào tài liệu một lần nữa và nhìn vào ví dụ ( mà không cần sự TRY...CATCH), sử dụng XACT_ABORT ONnguyên nhân một ngay lập tức roll-back của giao dịch: không có trạng thái giao dịch của "uncommittable" (xin lưu ý rằng không có đề cập đến ở tất cả trạng thái Giao dịch "không thể chấp nhận" trong SET XACT_ABORTtài liệu đó ).
Tôi nghĩ thật hợp lý khi kết luận rằng:
- việc giới thiệu
TRY...CATCHcấu trúc trong SQL Server 2005 đã tạo ra nhu cầu về trạng thái Giao dịch mới (nghĩa là "không thể truy cập") và XACT_STATE()chức năng để có được thông tin đó.
- kiểm tra
XACT_STATE()trong một CATCHkhối thực sự chỉ có ý nghĩa nếu cả hai điều sau là đúng:
XACT_ABORTlà OFF(người khác XACT_STATE()nên luôn luôn quay lại -1và @@TRANCOUNTsẽ là tất cả những gì bạn cần)
- Bạn có logic trong
CATCHkhối hoặc ở đâu đó trong chuỗi nếu các cuộc gọi được lồng nhau, điều đó tạo ra sự thay đổi (a COMMIThoặc thậm chí bất kỳ câu lệnh DML, DDL, v.v.) thay vì thực hiện a ROLLBACK. (đây là trường hợp sử dụng rất không điển hình) ** vui lòng xem ghi chú ở phía dưới, trong phần CẬP NHẬT 3, liên quan đến khuyến nghị không chính thức của Microsoft để luôn kiểm tra XACT_STATE()thay vì @@TRANCOUNTvà tại sao thử nghiệm cho thấy lý do của họ không được đưa ra.
- Phần lớn việc giới thiệu
TRY...CATCHcấu trúc trong SQL Server 2005 đã làm lỗi thuộc tính XACT_ABORT ONphiên vì nó cung cấp mức độ kiểm soát lớn hơn đối với Giao dịch (ít nhất bạn có tùy chọn COMMIT, miễn là XACT_STATE()không trả lại -1).
Một cách khác để xem xét điều này là, trước SQL Server 2005 , XACT_ABORT ONđã cung cấp một cách dễ dàng và đáng tin cậy để dừng xử lý khi xảy ra lỗi, so với việc kiểm tra @@ERRORsau mỗi câu lệnh.
- Mã ví dụ tài liệu cho
XACT_STATE()là sai, hoặc tốt nhất là sai lệch, trong đó nó hiển thị kiểm tra XACT_STATE() = 1khi nào XACT_ABORTlà ON.
Phần dài ;-)
Có, mã ví dụ trên MSDN hơi khó hiểu (xem thêm: @@ TRANCOUNT (Phục hồi) so với XACT_STATE ) ;-). Và, tôi cảm thấy nó sai lệch bởi vì nó hiển thị một cái gì đó vô nghĩa (vì lý do mà bạn đang hỏi về: bạn thậm chí có thể có một giao dịch "có thể giao dịch" trong CATCHkhối khi XACT_ABORTcó ON), hoặc thậm chí nếu có thể, nó vẫn tập trung vào một khả năng kỹ thuật mà ít ai muốn hoặc cần, và bỏ qua lý do người ta có thể cần nó hơn.
Nếu có một lỗi đủ nghiêm trọng bên trong khối TRY, điều khiển sẽ chuyển vào CATCH. Vì vậy, nếu tôi ở trong CATCH, tôi biết rằng giao dịch đã có vấn đề và thực sự điều hợp lý duy nhất cần làm trong trường hợp này là đẩy lùi nó, phải không?
Tôi nghĩ sẽ hữu ích nếu chúng tôi đảm bảo rằng chúng tôi ở trên cùng một trang liên quan đến ý nghĩa của các từ và khái niệm nhất định:
"Lỗi đủ nghiêm trọng": Chỉ cần rõ ràng, TRY ... CATCH sẽ bẫy hầu hết các lỗi. Danh sách những thứ sẽ không bị bắt được liệt kê trên trang MSDN được liên kết đó, trong phần "Lỗi không bị ảnh hưởng bởi phần Xây dựng CATCH TRY".
"nếu tôi ở trong CATCH, tôi biết rằng giao dịch đã có vấn đề" (em phas được thêm vào): Nếu bằng "giao dịch", bạn có nghĩa là đơn vị công việc logic được xác định bởi bạn bằng cách nhóm các báo cáo vào một giao dịch rõ ràng, sau đó rất có thể là có Tôi nghĩ rằng hầu hết mọi người trong DB chúng ta sẽ có xu hướng đồng ý rằng quay ngược lại là "điều hợp lý duy nhất để làm" vì chúng ta có thể có một cái nhìn tương tự về cách thức và lý do tại sao chúng ta sử dụng các giao dịch rõ ràng và hình dung những bước nào sẽ tạo nên một đơn vị nguyên tử của công việc.
Nhưng, nếu bạn có nghĩa là các đơn vị công việc thực tế đang được nhóm vào giao dịch rõ ràng, thì không, bạn không biết rằng chính giao dịch đã có vấn đề. Bạn chỉ biết rằng một câu lệnh thực thi trong giao dịch được xác định rõ ràng đã gây ra lỗi. Nhưng nó có thể không phải là một tuyên bố DML hoặc DDL. Và ngay cả khi đó là một tuyên bố DML, bản thân Giao dịch vẫn có thể được ủy quyền.
Với hai điểm đã nêu ở trên, có lẽ chúng ta nên rút ra sự khác biệt giữa các giao dịch mà bạn "không thể" cam kết và những điểm mà bạn "không muốn" cam kết.
Khi XACT_STATE()trả về a 1, điều đó có nghĩa là Giao dịch là "có thể thực hiện được", rằng bạn có lựa chọn giữa COMMIThoặc ROLLBACK. Bạn có thể không muốn cam kết điều đó, nhưng nếu vì một số lý do khó thực hiện ngay cả với một ví dụ - vì lý do bạn muốn, ít nhất bạn có thể vì một số phần của Giao dịch đã hoàn thành thành công.
Nhưng khi XACT_STATE()trả về a -1, thì bạn thực sự cần ROLLBACKbởi vì một phần của Giao dịch đã rơi vào trạng thái xấu. Bây giờ, tôi đồng ý rằng nếu kiểm soát đã được chuyển đến khối CATCH, thì nó chỉ đủ để kiểm tra @@TRANCOUNT, bởi vì ngay cả khi bạn có thể thực hiện Giao dịch, tại sao bạn lại muốn?
Nhưng nếu bạn chú ý ở đầu ví dụ, cài đặt XACT_ABORT ONthay đổi mọi thứ một chút. Bạn có thể có một lỗi thông thường, sau khi làm BEGIN TRANmà sẽ vượt qua kiểm soát khối catch khi XACT_ABORTlà OFFvà XACT_STATE () sẽ trở lại 1. NHƯNG, nếu XACT_ABORT là ON, thì Giao dịch bị "hủy bỏ" (nghĩa là không hợp lệ) cho bất kỳ lỗi 'ol nào và sau đó XACT_STATE()sẽ trả về -1. Trong trường hợp này, có vẻ như vô ích để kiểm tra XACT_STATE()trong CATCHkhối vì nó luôn luôn có vẻ trở lại một -1khi XACT_ABORTlà ON.
Vậy thì XACT_STATE()để làm gì? Một số manh mối là:
Trang MSDN cho TRY...CATCH, trong phần "Giao dịch không thể chấp nhận và XACT_STATE", cho biết:
Một lỗi thông thường kết thúc một giao dịch bên ngoài khối TRY khiến giao dịch đi vào trạng thái không thể sửa chữa khi lỗi xảy ra bên trong khối TRY.
Trang MSDN cho SET XACT_ABORT , trong phần "Ghi chú", cho biết:
Khi SET XACT_ABORT TẮT, trong một số trường hợp, chỉ có câu lệnh Transact-SQL gây ra lỗi được khôi phục và giao dịch tiếp tục xử lý.
và:
XACT_ABORT phải được đặt BẬT cho các câu lệnh sửa đổi dữ liệu trong một giao dịch ngầm hoặc rõ ràng đối với hầu hết các nhà cung cấp OLE DB, bao gồm cả SQL Server.
Trang MSDN cho BEGIN TRANSACTION , trong phần "Ghi chú", cho biết:
Giao dịch cục bộ được bắt đầu bởi câu lệnh BEGIN TRANSACTION được chuyển thành giao dịch phân tán nếu các hành động sau được thực hiện trước khi tuyên bố được cam kết hoặc khôi phục:
- Một câu lệnh INSERT, DELETE hoặc UPDATE tham chiếu bảng từ xa trên máy chủ được liên kết được thực thi. Câu lệnh INSERT, UPDATE hoặc DELETE không thành công nếu nhà cung cấp OLE DB được sử dụng để truy cập máy chủ được liên kết không hỗ trợ giao diện ITransactionJoin.
Việc sử dụng được áp dụng nhiều nhất dường như nằm trong ngữ cảnh của các câu lệnh DML của Máy chủ được liên kết. Và tôi tin rằng tôi đã gặp phải điều này từ nhiều năm trước. Tôi không nhớ tất cả các chi tiết, nhưng nó có liên quan đến máy chủ từ xa không có sẵn và vì một lý do nào đó, lỗi đó không bị bắt trong khối TRY và không bao giờ được gửi đến CATCH và vì vậy nó đã xảy ra một CAM KẾT khi nó không nên có. Tất nhiên, đó có thể là một vấn đề của việc không XACT_ABORTđặt ra ONthay vì không kiểm tra XACT_STATE(), hoặc có thể cả hai. Và tôi nhớ lại việc đọc một cái gì đó nói rằng nếu bạn sử dụng Máy chủ được liên kết và / hoặc Giao dịch phân tán thì bạn cần sử dụng XACT_ABORT ONvà / hoặc XACT_STATE(), nhưng dường như tôi không thể tìm thấy tài liệu đó ngay bây giờ. Nếu tôi tìm thấy nó, tôi sẽ cập nhật điều này với liên kết.
Tuy nhiên, tôi đã thử một vài thứ và không thể tìm thấy một kịch bản có XACT_ABORT ONvà vượt qua sự kiểm soát đối với CATCHkhối có XACT_STATE()báo cáo 1.
Hãy thử các ví dụ sau để thấy ảnh hưởng của XACT_ABORTgiá trị XACT_STATE():
SET XACT_ABORT OFF;
BEGIN TRY
BEGIN TRAN;
SELECT 1/0 AS [DivideByZero]; -- error, yo!
COMMIT TRAN;
END TRY
BEGIN CATCH
SELECT @@TRANCOUNT AS [@@TRANCOUNT],
XACT_STATE() AS [XactState],
ERROR_MESSAGE() AS [ErrorMessage]
IF (@@TRANCOUNT > 0)
BEGIN
ROLLBACK;
END;
END CATCH;
GO ------------------------------------------------
SET XACT_ABORT ON;
BEGIN TRY
BEGIN TRAN;
SELECT 1/0 AS [DivideByZero]; -- error, yo!
COMMIT TRAN;
END TRY
BEGIN CATCH
SELECT @@TRANCOUNT AS [@@TRANCOUNT],
XACT_STATE() AS [XactState],
ERROR_MESSAGE() AS [ErrorMessage]
IF (@@TRANCOUNT > 0)
BEGIN
ROLLBACK;
END;
END CATCH;
GO ------------------------------------------------
SET XACT_ABORT ON;
BEGIN TRY
SELECT 1/0 AS [DivideByZero]; -- error, yo!
END TRY
BEGIN CATCH
SELECT @@TRANCOUNT AS [@@TRANCOUNT],
XACT_STATE() AS [XactState],
ERROR_MESSAGE() AS [ErrorMessage]
END CATCH;
CẬP NHẬT
Mặc dù không phải là một phần của Câu hỏi ban đầu, dựa trên những nhận xét về Câu trả lời này:
Tôi đã đọc qua các bài viết của Erland về Xử lý lỗi và giao dịch trong đó anh ta nói rằng đó XACT_ABORTlà OFFmặc định vì lý do di sản và thông thường chúng ta nên đặt nó thành ON.
...
"... nếu bạn làm theo khuyến nghị và chạy với SET XACT_ABORT ON, giao dịch sẽ luôn bị hủy bỏ."
Trước khi sử dụng XACT_ABORT ONở mọi nơi, tôi sẽ đặt câu hỏi: chính xác những gì đang đạt được ở đây? Tôi không thấy cần phải làm và thường ủng hộ rằng bạn chỉ nên sử dụng nó khi cần thiết. Bạn có muốn ROLLBACKxử lý đủ dễ dàng hay không bằng cách sử dụng mẫu được hiển thị trong câu trả lời của @ Remus hoặc mẫu mà tôi đã sử dụng trong nhiều năm về cơ bản là giống nhau nhưng không có Điểm lưu, như được hiển thị trong câu trả lời này (mà xử lý các cuộc gọi lồng nhau):
Chúng tôi có bắt buộc phải xử lý Giao dịch bằng Mã C # cũng như trong thủ tục được lưu trữ không
CẬP NHẬT 2
Tôi đã thử nghiệm thêm một chút, lần này bằng cách tạo một Ứng dụng .NET Console nhỏ, tạo Giao dịch trong lớp ứng dụng, trước khi thực hiện bất kỳ SqlCommandđối tượng nào (tức là thông qua using (SqlTransaction _Tran = _Connection.BeginTransaction()) { ...), cũng như sử dụng lỗi hủy bỏ hàng loạt thay vì chỉ một câu lệnh -borting lỗi, và thấy rằng:
- Giao dịch "không phổ biến" là một giao dịch đã được khôi phục, phần lớn đã được khôi phục (các thay đổi đã được hoàn tác), nhưng
@@TRANCOUNTvẫn còn> 0.
- Khi bạn có một Giao dịch "không có ích", bạn không thể phát hành
COMMITvì nó sẽ tạo ra và lỗi nói rằng Giao dịch là "không thể chấp nhận được". Bạn cũng không thể bỏ qua nó / không làm gì vì một lỗi sẽ được tạo khi lô kết thúc nói rằng lô đã hoàn thành với một giao dịch kéo dài, không thể chấp nhận được và nó sẽ được khôi phục (vì vậy, ừm, nếu nó sẽ tự động quay lại, Tại sao phải ném lỗi?). Vì vậy, bạn phải đưa ra một rõ ràng ROLLBACK, có thể không phải trong CATCHkhối ngay lập tức , nhưng trước khi lô kết thúc.
- Trong một
TRY...CATCHcấu trúc, khi XACT_ABORTlà OFF, lỗi đó sẽ chấm dứt giao dịch tự động có họ xảy ra bên ngoài của một TRYkhối, chẳng hạn như các lỗi hàng loạt hủy, sẽ lùi lại công việc nhưng không chấm dứt Tranasction, để lại nó như là "uncommitable". Phát hành a ROLLBACKlà một hình thức cần thiết hơn để đóng Giao dịch, nhưng công việc đã được khôi phục.
- Khi
XACT_ABORTlà ON, hầu hết các lỗi làm hàng loạt hủy, và do đó cư xử như mô tả trong điểm đạn trực tiếp trên (# 3).
XACT_STATE(), ít nhất là trong một CATCHkhối, sẽ hiển thị -1lỗi hủy bỏ hàng loạt nếu có Giao dịch hoạt động tại thời điểm xảy ra lỗi.
XACT_STATE()đôi khi trả lại 1ngay cả khi không có Giao dịch hoạt động. Nếu @@SPID(trong số những người khác) có trong SELECTdanh sách cùng với XACT_STATE(), thì XACT_STATE()sẽ trả về 1 khi không có Giao dịch hoạt động. Hành vi này bắt đầu trong SQL Server 2012 và tồn tại vào năm 2014, nhưng tôi chưa thử nghiệm vào năm 2016.
Với những điểm trên trong tâm trí:
- Với các điểm số 4 và số 5, vì hầu hết các lỗi (hoặc tất cả?) Sẽ khiến Giao dịch trở nên "không thể thực hiện được", nên việc kiểm tra
XACT_STATE()trong CATCHkhối XACT_ABORTlà khi nào ONgiá trị được trả về sẽ luôn luôn là vô nghĩa -1.
- Kiểm tra
XACT_STATE()trong CATCHkhối khi XACT_ABORTcó OFFý nghĩa hơn bởi vì giá trị trả về ít nhất sẽ có một số biến thể vì nó sẽ trả về 1các lỗi hủy bỏ câu lệnh. Tuy nhiên, nếu bạn viết mã như hầu hết chúng ta, thì sự khác biệt này là vô nghĩa vì ROLLBACKdù sao bạn cũng sẽ gọi đơn giản vì thực tế là đã xảy ra lỗi.
- Nếu bạn tìm thấy một tình huống mà không trát phát hành một
COMMITtrong các CATCHkhối, sau đó kiểm tra giá trị của XACT_STATE(), và hãy chắc chắn SET XACT_ABORT OFF;.
XACT_ABORT ONdường như cung cấp ít hoặc không có lợi ích trên các TRY...CATCHcông trình.
- Tôi không thể tìm thấy kịch bản nào trong đó việc kiểm tra
XACT_STATE()cung cấp một lợi ích có ý nghĩa hơn là kiểm tra đơn giản @@TRANCOUNT.
- Tôi cũng có thể tìm thấy không có kịch bản mà
XACT_STATE()lợi nhuận 1trong một CATCHkhối khi XACT_ABORTlà ON. Tôi nghĩ đó là một lỗi tài liệu.
- Có, bạn có thể quay lại Giao dịch mà bạn không bắt đầu rõ ràng. Và trong bối cảnh sử dụng
XACT_ABORT ON, đó là một điểm cần thiết vì một lỗi xảy ra trong một TRYkhối sẽ tự động khôi phục các thay đổi.
- Cấu
TRY...CATCHtrúc có lợi ích XACT_ABORT ONtrong việc không tự động hủy toàn bộ Giao dịch và do đó cho phép Giao dịch (miễn là XACT_STATE()trả lại 1) được cam kết (ngay cả khi đây là trường hợp cạnh).
Ví dụ XACT_STATE()về -1khi trở về XACT_ABORTlà OFF:
SET XACT_ABORT OFF;
BEGIN TRY
BEGIN TRAN;
SELECT CONVERT(INT, 'g') AS [ConversionError];
COMMIT TRAN;
END TRY
BEGIN CATCH
DECLARE @State INT;
SET @State = XACT_STATE();
SELECT @@TRANCOUNT AS [@@TRANCOUNT],
@State AS [XactState],
ERROR_MESSAGE() AS [ErrorMessage];
IF (@@TRANCOUNT > 0)
BEGIN
SELECT 'Rollin back...' AS [Transaction];
ROLLBACK;
END;
END CATCH;
CẬP NHẬT 3
Liên quan đến mục số 6 trong phần CẬP NHẬT 2 (nghĩa là giá trị không chính xác có thể được trả về XACT_STATE()khi không có Giao dịch hoạt động):
- Hành vi kỳ quặc / sai lầm bắt đầu trong SQL Server 2012 (cho đến nay đã được thử nghiệm so với 2012 SP2 và 2014 SP1)
- Trong các phiên bản SQL Server 2005, 2008 và 2008 R2,
XACT_STATE()đã không báo cáo các giá trị dự kiến khi được sử dụng trong Triggers hoặc INSERT...EXECkịch bản: xact_state () không thể được sử dụng một cách đáng tin cậy để xác định liệu giao dịch có bị hủy hay không . Tuy nhiên, trong những phiên bản 3 (tôi chỉ thử nghiệm trên 2008 R2), XACT_STATE()không không sai báo cáo 1khi sử dụng trong một SELECTvới @@SPID.
Có một lỗi Connect được đệ trình chống lại hành vi được đề cập ở đây nhưng được đóng lại là "Theo thiết kế": XACT_STATE () có thể trả về trạng thái giao dịch không chính xác trong SQL 2012 . Tuy nhiên, thử nghiệm đã được thực hiện khi chọn từ DMV và kết luận rằng làm như vậy tự nhiên sẽ có một giao dịch được tạo ra hệ thống, ít nhất là đối với một số DMV. Nó cũng được nêu trong phản hồi cuối cùng của MS rằng:
Lưu ý rằng một câu lệnh IF và cũng là CHỌN không có TỪ, không bắt đầu giao dịch.
ví dụ: chạy CHỌN XACT_STATE () nếu bạn không có giao dịch hiện tại trước đó sẽ trả về 0.
Những tuyên bố không chính xác được đưa ra ví dụ sau:
SELECT @@TRANCOUNT AS [TRANCOUNT], XACT_STATE() AS [XACT_STATE], @@SPID AS [SPID];
GO
DECLARE @SPID INT;
SET @SPID = @@SPID;
SELECT @@TRANCOUNT AS [TRANCOUNT], XACT_STATE() AS [XACT_STATE], @SPID AS [SPID];
GO
Do đó, lỗi Connect mới:
XACT_STATE () trả về 1 khi được sử dụng trong SELECT với một số biến hệ thống nhưng không có mệnh đề TỪ
XIN LƯU Ý rằng trong "XACT_STATE () có thể trả về trạng thái giao dịch không chính xác trong SQL 2012" Kết nối mục được liên kết trực tiếp ở trên, Microsoft (tốt, đại diện của) tuyên bố:
@@ trancount trả về số lượng câu lệnh BEGIN TRAN. Do đó, nó không phải là một chỉ số đáng tin cậy về việc có một giao dịch hoạt động hay không. XACT_STATE () cũng trả về 1 nếu có giao dịch tự động hoạt động và do đó là một chỉ số đáng tin cậy hơn về việc có giao dịch đang hoạt động hay không.
Tuy nhiên, tôi không thể tìm thấy lý do để không tin tưởng @@TRANCOUNT. Thử nghiệm sau đây cho thấy @@TRANCOUNTthực sự trở lại 1trong giao dịch tự động cam kết:
--- begin setup
GO
CREATE PROCEDURE #TransactionInfo AS
SET NOCOUNT ON;
SELECT @@TRANCOUNT AS [TranCount],
XACT_STATE() AS [XactState];
GO
--- end setup
DECLARE @Test TABLE (TranCount INT, XactState INT);
SELECT * FROM @Test; -- no rows
EXEC #TransactionInfo; -- 0 for both fields
INSERT INTO @Test (TranCount, XactState)
EXEC #TransactionInfo;
SELECT * FROM @Test; -- 1 row; 1 for both fields
Tôi cũng đã thử nghiệm trên một bảng thực với Trình kích hoạt và @@TRANCOUNTtrong Trình kích hoạt đã báo cáo chính xác 1mặc dù không có Giao dịch rõ ràng nào được bắt đầu.
XACT_ABORTthànhONhayOFF.