Saya memiliki Insert
prosedur tersimpan yang akan memberi makan data ke Table1
dan mendapatkan Column1
nilai dari Table1
dan memanggil prosedur tersimpan kedua yang akan memberi makan Tabel2.
Tetapi ketika saya memanggil prosedur tersimpan kedua sebagai:
Exec USPStoredProcName
Saya mendapatkan kesalahan berikut:
Jumlah transaksi setelah EXECUTE menunjukkan jumlah pernyataan BEGIN dan COMMIT yang tidak sesuai. Hitungan sebelumnya = 1, hitungan saat ini = 0.
Saya telah membaca jawaban dalam pertanyaan lain semacam itu dan saya tidak dapat menemukan di mana tepatnya jumlah commit menjadi kacau.
sql
sql-server-2012
sqlexception
Vignesh Kumar A
sumber
sumber
Jawaban:
Jika Anda memiliki blok TRY / CATCH maka kemungkinan besar penyebabnya adalah Anda menangkap pengecualian pembatalan transaksi dan melanjutkan. Dalam blok CATCH Anda harus selalu memeriksa
XACT_STATE()
dan menangani transaksi yang dibatalkan dan tidak dapat dilakukan (ditakdirkan). Jika penelepon Anda memulai transaksi dan calee menemukan, katakanlah, kebuntuan (yang membatalkan transaksi), bagaimana callee akan mengkomunikasikan kepada penelepon bahwa transaksi telah dibatalkan dan tidak boleh dilanjutkan dengan 'bisnis seperti biasa'? Satu-satunya cara yang layak adalah memunculkan kembali pengecualian, memaksa pemanggil untuk menangani situasi tersebut. Jika Anda diam-diam menelan transaksi yang dibatalkan dan penelepon terus menganggap masih dalam transaksi asli, hanya kekacauan yang dapat memastikan (dan kesalahan yang Anda dapatkan adalah cara mesin mencoba melindungi dirinya sendiri).Saya sarankan Anda membahas penanganan Exception dan transaksi bersarang yang menunjukkan pola yang dapat digunakan dengan transaksi dan pengecualian bersarang:
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
sumber
xact_abort on
?if @xstate = -1 rollback;
Melihat contoh MSDN ini , kita tidak boleh mengembalikan transaksi penuh kecuali tidak ada transaksi luar (kecuali kita melakukannyabegin tran
). Saya pikir prosedurnya hanyarollback
jika kita memulai transaksi, yang akan memperbaiki masalah @ sparrow.Saya punya masalah ini juga. Bagi saya, alasannya adalah yang saya lakukan
return commit
dari pada
commit return
dalam satu prosedur tersimpan.
sumber
Hal ini biasanya terjadi ketika transaksi dimulai dan tidak dilakukan atau bukan rollback.
Jika terjadi kesalahan dalam prosedur tersimpan Anda, ini dapat mengunci tabel database karena transaksi tidak diselesaikan karena beberapa kesalahan runtime tanpa adanya penanganan pengecualian. Anda dapat menggunakan penanganan Exception seperti di bawah ini. SETEL XACT_ABORT
SET XACT_ABORT ON SET NoCount ON Begin Try BEGIN TRANSACTION //Insert ,update queries COMMIT End Try Begin Catch ROLLBACK End Catch
Sumber
sumber
Ketahuilah bahwa jika Anda menggunakan transaksi bertingkat, operasi ROLLBACK akan mengembalikan semua transaksi bertingkat termasuk yang paling luar.
Ini mungkin, dengan penggunaan dalam kombinasi dengan TRY / CATCH, menghasilkan kesalahan yang Anda jelaskan. Lihat selengkapnya di sini .
sumber
Ini juga dapat terjadi jika prosedur tersimpan Anda mengalami kegagalan kompilasi setelah membuka transaksi (mis. Tabel tidak ditemukan, nama kolom tidak valid).
Saya menemukan saya harus menggunakan 2 prosedur yang tersimpan, satu "pekerja" dan satu pembungkus dengan coba / tangkap keduanya dengan logika yang mirip dengan yang diuraikan oleh Remus Rusanu. Tangkapan pekerja digunakan untuk menangani kegagalan "normal" dan tangkapan pembungkus untuk menangani kesalahan kegagalan kompilasi.
https://msdn.microsoft.com/en-us/library/ms175976.aspx
Kesalahan Tidak Dipengaruhi oleh COBALAH… CATCH Construct
Semoga ini membantu orang lain menghemat beberapa jam debugging ...
sumber
Dalam kasus saya, kesalahan itu disebabkan oleh bagian
RETURN
dalamBEGIN TRANSACTION
. Jadi saya punya sesuatu seperti ini:Begin Transaction If (@something = 'foo') Begin --- do some stuff Return End commit
dan itu harus:
Begin Transaction If (@something = 'foo') Begin --- do some stuff Rollback Transaction ----- THIS WAS MISSING Return End commit
sumber
Bagi saya setelah debugging ekstensif, perbaikan itu hanyalah lemparan yang hilang; pernyataan di tangkapan setelah rollback. Tanpanya pesan kesalahan jelek ini akan berakhir dengan Anda.
begin catch if @@trancount > 0 rollback transaction; throw; --allows capture of useful info when an exception happens within the transaction end catch
sumber
Saya mendapatkan pesan kesalahan yang sama, kesalahan saya adalah saya mendapat titik koma di akhir baris COMMIT TRANSACTION
sumber
Saya mengalami kesalahan ini sekali setelah menghilangkan pernyataan ini dari transaksi saya.
COMMIT TRANSACTION [MyTransactionName]
sumber
Menurut pendapat saya jawaban yang diterima dalam banyak kasus berlebihan.
Penyebab error seringnya ketidakcocokan antara BEGIN dan COMMIT sebagaimana dinyatakan dengan jelas oleh error tersebut. Ini berarti menggunakan:
Begin Begin -- your query here End commit
dari pada
Begin Transaction Begin -- your query here End commit
menghilangkan Transaksi setelah Mulai menyebabkan kesalahan ini!
sumber
Pastikan Anda tidak memiliki beberapa transaksi dalam prosedur / kueri yang sama di mana satu atau lebih transaksi tidak terikat.
Dalam kasus saya, saya secara tidak sengaja memiliki pernyataan BEGIN TRAN dalam kueri
sumber
Ini juga dapat bergantung pada cara Anda memanggil SP dari kode C # Anda. Jika SP mengembalikan beberapa nilai jenis tabel kemudian memanggil SP dengan ExecuteStoreQuery, dan jika SP tidak mengembalikan nilai apa pun, panggil SP dengan ExecuteStoreCommand
sumber
Hindari pemakaian
pernyataan saat Anda menggunakan
BEGIN TRY ... END TRY BEGIN CATCH ... END CATCH
dan
BEGIN, COMMIT & ROLLBACK
pernyataan dalam prosedur tersimpan SQL
sumber
Jika Anda memiliki struktur kode seperti:
SELECT 151 RETURN -151
Kemudian gunakan:
SELECT 151 ROLLBACK RETURN -151
sumber