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 CATCH
vớ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ề 1
bên trong một CATCH
khối khi @@TRANCOUNT > 0
và thuộc tính phiên XACT_ABORT
là 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_ABORT
có 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 TRY
khối. Những tuyên bố tương tự trong một TRY
khố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_ABORT
là OFF
, khi kiểm soát được thông qua vào CATCH
khố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_ABORT
là ON
sau đó 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ộtROLLBACK
mà 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_ABORT
là 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...CATCH
cấ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 ON
nguyê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_ABORT
tà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...CATCH
cấ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 CATCH
khối thực sự chỉ có ý nghĩa nếu cả hai điều sau là đúng:
XACT_ABORT
là OFF
(người khác XACT_STATE()
nên luôn luôn quay lại -1
và @@TRANCOUNT
sẽ là tất cả những gì bạn cần)
- Bạn có logic trong
CATCH
khố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 COMMIT
hoặ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ì @@TRANCOUNT
và 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...CATCH
cấu trúc trong SQL Server 2005 đã làm lỗi thuộc tính XACT_ABORT ON
phiê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 @@ERROR
sau 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() = 1
khi nào XACT_ABORT
là 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 CATCH
khối khi XACT_ABORT
có 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 COMMIT
hoặ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 ROLLBACK
bở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 ON
thay đổ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 TRAN
mà sẽ vượt qua kiểm soát khối catch khi XACT_ABORT
là OFF
và 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 CATCH
khối vì nó luôn luôn có vẻ trở lại một -1
khi XACT_ABORT
là 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 ON
thay 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 ON
và / 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 ON
và vượt qua sự kiểm soát đối với CATCH
khố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_ABORT
giá 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_ABORT
là OFF
mặ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 ROLLBACK
xử 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
@@TRANCOUNT
vẫ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
COMMIT
vì 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 CATCH
khối ngay lập tức , nhưng trước khi lô kết thúc.
- Trong một
TRY...CATCH
cấu trúc, khi XACT_ABORT
là 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 TRY
khố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 ROLLBACK
là 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_ABORT
là 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 CATCH
khối, sẽ hiển thị -1
lỗ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 1
ngay cả khi không có Giao dịch hoạt động. Nếu @@SPID
(trong số những người khác) có trong SELECT
danh 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 CATCH
khối XACT_ABORT
là khi nào ON
giá trị được trả về sẽ luôn luôn là vô nghĩa -1
.
- Kiểm tra
XACT_STATE()
trong CATCH
khối khi XACT_ABORT
có 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ề 1
cá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ì ROLLBACK
dù 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
COMMIT
trong các CATCH
khối, sau đó kiểm tra giá trị của XACT_STATE()
, và hãy chắc chắn SET XACT_ABORT OFF;
.
XACT_ABORT ON
dường như cung cấp ít hoặc không có lợi ích trên các TRY...CATCH
cô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 1
trong một CATCH
khối khi XACT_ABORT
là 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 TRY
khối sẽ tự động khôi phục các thay đổi.
- Cấu
TRY...CATCH
trúc có lợi ích XACT_ABORT ON
trong 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ề -1
khi trở về XACT_ABORT
là 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...EXEC
kị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 1
khi sử dụng trong một SELECT
vớ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 @@TRANCOUNT
thực sự trở lại 1
trong 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à @@TRANCOUNT
trong Trình kích hoạt đã báo cáo chính xác 1
mặc dù không có Giao dịch rõ ràng nào được bắt đầu.
XACT_ABORT
thànhON
hayOFF
.