Saya memiliki prosedur tersimpan yang disebut dalam blok insert-exec:
insert into @t
exec('test')
Bagaimana saya bisa menangani pengecualian yang dihasilkan dalam prosedur tersimpan dan masih melanjutkan pemrosesan?
Kode berikut menggambarkan masalah. Yang ingin saya lakukan adalah mengembalikan 0 atau -1 tergantung pada keberhasilan atau kegagalan exec()
panggilan internal :
alter procedure test -- or create
as
begin try
declare @retval int;
-- This code assumes that PrintMax exists already so this generates an error
exec('create procedure PrintMax as begin print ''hello world'' end;')
set @retval = 0;
select @retval;
return(@retval);
end try
begin catch
-- if @@TRANCOUNT > 0 commit;
print ERROR_MESSAGE();
set @retval = -1;
select @retval;
return(@retval);
end catch;
go
declare @t table (i int);
insert into @t
exec('test');
select *
from @t;
Masalah saya adalah return(-1)
. Jalur sukses baik-baik saja.
Jika saya meninggalkan blok coba / tangkap dalam prosedur tersimpan, maka kesalahan dinaikkan dan insert gagal. Namun, yang ingin saya lakukan adalah menangani kesalahan dan mengembalikan nilai yang bagus.
Kode as is mengembalikan pesan:
Msg 3930, Level 16, State 1, Line 6
The current transaction cannot be committed and cannot support operations that write to the log file. Roll back the transaction.
Ini mungkin pesan kesalahan terburuk yang saya temui. Tampaknya benar-benar berarti "Anda tidak menangani kesalahan dalam transaksi bersarang."
Jika saya memasukkan if @@TRANCOUNT > 0
, maka saya mendapatkan pesan:
Msg 3916, Level 16, State 0, Procedure gordontest, Line 7
Cannot use the COMMIT statement within an INSERT-EXEC statement unless BEGIN TRANSACTION is used first.
Saya sudah mencoba bermain-main dengan memulai / melakukan pernyataan transaksi, tetapi sepertinya tidak ada yang berhasil.
Jadi, bagaimana saya bisa memiliki prosedur tersimpan menangani kesalahan tanpa membatalkan transaksi keseluruhan?
Edit dalam menanggapi Martin:
Kode panggilan sebenarnya adalah:
declare @RetvalTable table (retval int);
set @retval = -1;
insert into @RetvalTable
exec('
mendeklarasikan @retval int; exec @retval = '+ @ query +'; pilih @retval ');
select @retval = retval from @RetvalTable;
Di mana @query
prosedur panggilan tersimpan? Tujuannya adalah untuk mendapatkan nilai balik dari prosedur tersimpan. Jika ini dimungkinkan tanpa insert
(atau, lebih khusus, tanpa memulai transaksi), itu akan bagus.
Saya tidak bisa mengubah prosedur yang tersimpan secara umum untuk menyimpan nilai dalam tabel, karena ada terlalu banyak. Salah satunya gagal, dan saya bisa memodifikasinya. Solusi terbaik saya saat ini adalah sesuatu seperti:
if (@StoredProcedure = 'sp_rep__post') -- causing me a problem
begin
exec @retval = sp_rep__post;
end;
else
begin
-- the code I'm using now
end;
select @retval; return @retval
di bagian akhir. Jika Anda tahu cara lain untuk mendapatkan nilai kembali dari panggilan prosedur tersimpan dinamis, saya ingin tahu.
DECLARE @RC INT;EXEC sp_executesql N'EXEC @RC = test', N'@RC INT OUTPUT', @RC = @RC OUTPUT;insert into @t VALUES (@RC)
declare @t table (i int);declare @RC int;exec @RC = test;insert into @t values (@RC);select * from @t;
bekerja dengan baik.