PDA

View Full Version : برنگشتن پیغام RAISERROR به Application بعداز دستورات insert, delete, update در StoredProcedure



mosafer_deltang
یک شنبه 16 بهمن 1390, 21:16 عصر
با سلام خدمت اساتید

یک پروسیجر مثل این در نظر بگیرید

CREATE PROCEDURE Insert1
AS
BEGIN
insert into Table_1 (param1, param2) values (1, 2)
RAISERROR('Error Message', 16, 1)
END


وقتی از داخل Application فراخوانیش می کنم پیغام دستور RAISERROR رو نشون نمیده ولی وقتی RAISERROR قبل از insert میاد exception رخ میده و پیغام نمایش داده میشه. چرا اینطوریه؟ و باید چه کار کنم؟
لطفا راهنمایی کنید با تشکر

tiphooo
دوشنبه 17 بهمن 1390, 09:05 صبح
RAISERROR برای این است که اگر پروسبجر شما نتواند آن عملیات را انجام دهد پیغام خطای شما را برگرداند ظاهرا دستور INSERT شما با موفقیت انجام شده و به RAISERROR نمی رسد.

mosafer_deltang
دوشنبه 17 بهمن 1390, 15:35 عصر
نه دوست عزیز اینطور نیست. اگه دستور insert موفقیت آمیز هم نباشه باز هم پیغام رو نشون نمیده

دوستان لطفا راهنمایی کنید. به هر حال من میخوام یه پیغام به برنامه برگردونم.

اصلا داستان اینه:

من تو پروسیجرم چند تا دستور insert و update را بین begin transaction و commit transaction نوشتم. دستور insert آخر روی یه جدول insert می کنه که روی اون جدول تریگر after insert نوشته شده و توی اون تریگر یه شرط را چک میکنه اگه برقرار نبود RAISERROR و بعد Rollback میشه و در نتیجه همه تراکنش هایی که توی transaction نوشته شده بودن Rollback میشن. ولی از آنجایی که قبل از دستور insert ی که روی آن، تریگر نوشته شده چند تراکنش دیگه اجرا میشن بنابراین پیغام RAISERROR را نشون نمیده. بعد که دقت کردم فهمیدم پیغام دستور RAISERROR فقط وقتی به برنامه برمیگرده که قبلش دستورات insert, delete, update نباشه!!!

از دریافت هر گونه راهنمایی خوشحال می شویم :لبخندساده:

یوسف زالی
دوشنبه 17 بهمن 1390, 20:01 عصر
سلام.
از return ها استفاده کنید.
در مود های مختلف اعداد متفاوتی return کنید و در UI با گرفتن اون عدد وارد شرطهایی بشید که پیغام متناسبی رو نمایش می ده.

tiphooo
دوشنبه 17 بهمن 1390, 20:04 عصر
اینکه نباید قبلش دستورات INSERT ,UPDATE , DELETE باشه فرقی به حال RAISE نداره شما در صورت یک شرط خاص RAISE را اجرا می کنید اما زمانی که این دستورات را اجرا می کنید شرط RAISE شما قاعدتا با با دستور ROWCOUNT@@ خواهد بود به نحوی که مثلا اگر INSERT انجام نشد یک پیغام برگردانید و بقیه عملیات را ROLLBACK کنید
به صورت

IF @@ROWCOUNT=0
BEGIN
RAISERROR(ErrorMessage', 16, 1)
ROLLBACK TRANSACTION
END
و اینکه این RAISE که شما نوشتید تحت هیچ شرط خاصی نیست ,و برای چک کردن بروز خطا به صورت زیر عمل کنید
IF @@ERROR=0
COMMIT TRANSACTION
ELSE
BEGIN
RAISERROR(ErrorMessage', 16, 1)
ROLLBACK TRANSACTION
END

mosafer_deltang
دوشنبه 17 بهمن 1390, 23:44 عصر
اینکه نباید قبلش دستورات INSERT ,UPDATE , DELETE باشه فرقی به حال RAISE نداره شما در صورت یک شرط خاص RAISE را اجرا می کنید اما زمانی که این دستورات را اجرا می کنید شرط RAISE شما قاعدتا با با دستور ROWCOUNT@@ خواهد بود به نحوی که مثلا اگر INSERT انجام نشد یک پیغام برگردانید و بقیه عملیات را ROLLBACK کنید



به خاطر دو دستور @@ROWCOUNT و @@ERROR ممنون. نمیدونستم

ولی این مشکل که دستور RAISERROR بعد از insert, delete, update پیغام رو برنمیگردونه همچنان باقی است و فرقی نمیکنه که اون رو توی یک شرط بذاریمش که اون شرط برقرار بشه و به دستور RAISERROR برسه یا اصلا براش شرط نذاریم به هر حال قاعدتا به محض این که به این دستور برسه باید پیغام رو برگردونه که برنمیگردونه

البته همونطور که you-see گفتن میشه از return استفاده کرد ولی میخواستم بدونم مشکل این حالت چیه
به لاتین سرچ کردم خیلی ها مشکل برنگشتن پیغام رو داشتن یه راه حل هایی هم داده بودن ولی هر کدوم که انجام دادم درست نشد

baktash.n81@gmail.com
سه شنبه 18 بهمن 1390, 07:58 صبح
سلام

در بعضی مواقع یک کد باعث بروز خطا در SQL می شه ... و SQL حودش یه خطا Raise می کنه و شما با توابع زیر می تونی اون خطا رو بگیری و تو لایه APP هندلش کنی ...

ERROR_NUMBER()

ERROR_MESSAGE()

ERROR_SEVERITY()

ERROR_STATE()

ERROR_LINE()

ERROR_PROCEDURE()


نکته ای که در خصوص Raiserror وجود داره ... اینه که Raiserror به شما کمک می کنه که خطایی رو ایجاد کنید و با کمک توابع بالا خطایی رو که ایجاد کردید تشخیص بدید ... این تابع به تنهایی خطایی رو به برنامه شما بر نمی گردونه ... کاری که برای شما انجام میده و خیلی مهمه اینه که کنترل رو به Catch می بره ...
کاربردش چیه ... مثلا شما می خوای چک کنی که کاربر در یک فیلد عدد 5 وارد نکنه ... (البته با فرض اینکه تو لایه App نمی تونی کنترلش کنی مثلا یک برنامه بر اساس یه سرس اتفاقات داره این اطلاعات رو می فرسته)
خوب توی SP مربوط به Insert می گی اگه پارامتر پاس شده 5 بود Raiserror کنه و بپره به بلوک Catch و اونجا با کمک مثلا Error_Message() پیغام خطایی که خود ت Raise کردی رو به اون کاربر بر می گردونی ...

ممکنه کد شما 40 یا 50 تا شرط رو چک کنه ... و برای هر کدوم میای خطا با کد های مختلف Raise می کنی و کد خطا رو با یک دستور Catch می گیری و به برنامه بر می گردونی اونجا پیغام مناسب رو به کاربر می دی ...

در ضمن می تونی به کمک sp_addmessage پیغامهاتو تو SQL ثبت کنی ....

mosafer_deltang
سه شنبه 18 بهمن 1390, 16:15 عصر
این تابع به تنهایی خطایی رو به برنامه شما بر نمی گردونه ... کاری که برای شما انجام میده و خیلی مهمه اینه که کنترل رو به Catch می بره ...


با تشکر از توجه شما و ممنون به خاطر توابع مفیدی که به من معرفی کردید.

مشکل من دقیقا همینه که کنترل رو به Catch نمی بره


try
ADOCommand1.CommandText := 'exec Insert1';
ADOCommand1.Execute;
except
ShowMessage('dddd');
end;


پیغام 'dddd' نمایش داده نمیشه یعنی هیچ exception ی رخ نمیده

baktash.n81@gmail.com
چهارشنبه 19 بهمن 1390, 07:51 صبح
مشکل اینجاست ... فقط مقدارهایی که در Return یا Select وجودداره به APP بر میگرده ... از Try Catch تو خود SP استفاده کنید ... این مثال رو ببین ...


alter proc hitest
as
begin
begin try
raiserror('hi',16,1)
end try
begin catch
select ERROR_MESSAGE() as ErrorMessage
end catch
end
exec hitest

baktash.n81@gmail.com
چهارشنبه 19 بهمن 1390, 07:53 صبح
در واقع اون Select داخل دستور Catch هست که پیغام خطارو به APP بر می گردونه ... خودتابع Raiseerror اگه بدون Try و Catch استفاده بشه شبیه دستور Print می مونه (به گفته Help SQL)