raiseerror-nowait

استفاده از گزینه NOWAIT همراه با عبارت RAISERROR

اسکریپت های T-SQL و پروسیجرها، دستورات PRINT و خروجی RAISERROR خود را به گونه ای تولید نمی کنند که شما را از پیشرفت کد مطلع نگه دارد. معمولاً قبل از دیدن پیام های خروجی، باید منتظر بمانیم تا مراحل تکمیل شود. حال چگونه می توانیم بینشی از پیشرفت کد کسب کنیم؟

راه حل این است که از گزینه WITH NOWAIT و عبارت RAISERROR استفاده کنید. ممکن است تعجب آور باشد اما استفاده از RAISERROR نیازی به وجود شرایط خطا ندارد. اگر سطح شدت داده شده به RAISERROR  صفر تا 10 باشد، SQL Server با RAISERROR به عنوان یک پیام ساده برخورد می کند و اصلاً یک خطا نیست. اجرا با عبارت بعدی ادامه می یابد، حتی اگر یک بلوک TRY/CATCH وجود داشته باشد یا اگر SET XACT_ABORT روشن باشد. از ترکیب شدت RAISERROR از 0 تا 10 و عبارت WITH NOWAIT برای عبارتی استفاده کنید که خروجی را فوراً به پیام های ویندوز ارسال می کند، مانند این:

RAISERROR (‘Now that”s what I call a message!’, 0, 1) WITH NOWAIT

اگر پیام‌ها توسط پنجره‌های Results SSMS یا پنجره‌های Grids در Query Analyzer مبهم شدند، فریب نخورید. هنگامی که نتایج پرس و جو به یک شبکه ارسال می شود، این پنجره ها به محض شروع اجرای دستور نشان داده می شوند و پنجره پیام ها پنهان می شود مگر اینکه هیچ نتیجه ای وجود نداشته باشد. دو راه برای رسیدگی به این موضوع وجود دارد. یکی از گزینه ها ارسال نتایج به متن با استفاده از منو یا CTRL+T است. گزینه دیگر این است که اجازه دهید نتایج به شبکه بروند و روی پنجره پیام ها کلیک کنید یا از دستور منوی SSMS Window/Next Pane استفاده کنید که به طور پیش فرض به کلید F6 یا Shift+F6 در Query Analyzer گره خورده است.

پس از ارسال نتایج به متن با CTRL+T این اسکریپت را امتحان کنید:

DECLARE @time char(8)

PRINT ‘1 PRINT before anything else      ‘                 + convert (varchar(30), getdate(), 8)

SET @time= convert (varchar(30), getdate(), 8)

RAISERROR (‘2 RAISERROR before WITHOUT NOWAIT %s’, 0, 1, @time)

‘WAITFOR DELAY ’00:00:05

PRINT ‘3 PRINT after the first delay     ‘                  + convert (varchar(30), getdate(), 8)

SET @time= convert (varchar(30), getdate(), 8)

RAISERROR (‘4 RAISERROR with NOWAIT           %s’, 0, 1, @time)

         ‘WITH NOWAITWAITFOR DELAY ’00:00:10

PRINT ‘5 PRINT after the second delay    ‘                      + convert (varchar(30), getdate(), 8)

چیزی که خواهید دید چیزی شبیه به این نتیجه است:

1PRINT before anything else 15:47:14

2RAISERROR before WITHOUT NOWAIT 15:47:14

3PRINT after the first delay 15:47:19

4RAISERROR WITH NOWAIT 15:47:19

این نتایج در 5 ثانیه نشان داده می شود. نه دستورات PRINT در خطوط 1 و 3 و نه RAISERROR در خط 2 قبل از اجرای RAISERROR WITH NOWAIT در خط 4 ظاهر نمی شوند. سپس بعد از 10 ثانیه دیگر خواهید دید:

5PRINT after the second delay 15:47:29

همانطور که از مهرهای زمانی می بینید، خطوط 1 و 2 در ساعت 15:47:14 اجرا شدند و سپس 5 ثانیه تاخیر تا ساعت 15:47:19 وجود داشت که خطوط 3 و 4 اجرا شدند و ظاهر شدند. این عبارت NOWAIT در RAISERROR است که خط 4 را تولید می کند و خطوط 1 تا 4 را به پنجره پیام می آورد.

یکی از راه‌هایی که می‌توان بند NOWAIT را ساده تر کرد، نوشتن آن در یک پروسیجر ساده  است :

SET ANSI_NULLS ON

GO

SET QUOTED_IDENTIFIER ON

GO

CREATE proc [dbo].[ns_log_nowait]     @Msg nvarchar(2047)

/* Send a message to the caller so that it’s available * immediately.** example

‘print ‘before the call

‘exec dbo.ns_log_nowait ‘This is the immediate message

‘waitfor delay ’00:00:10

‘print ‘This is after a 10 second delay

compare this to

‘print ‘before the call

raiserror (‘this is the msg’, 0, 1)

‘waitfor delay ’00:00:10

‘print ‘This is after a 10 second dela’

******************************************/*****************

AS   

RAISERROR (@Msg, 0, 1)

WITH NOWAIT

go

GRANT EXECUTE on [dbo].[ns_log_nowait] to PUBLIC

go

RAISERROR با شدت کمتر از 11 به عنوان یک خطا در ساختار TRY/CATCH تلقی نمی شود و NOWAIT هیچ تأثیری بر این رفتار ندارد. برای مشاهده اینکه RAISERROR با شدت 0 مانند یک عبارت چاپی رفتار می شود، این اسکریپت را در SSMS امتحان کنید:

DECLARE @time char(8)

BEGIN TRY 

   PRINT ‘1 PRINT in the TRY block ‘             + convert (varchar(30), getdate(), 8) 

   SET @time= convert (varchar(30), getdate(), 8)   

RAISERROR (‘2 RAISERROR with NOWAIT %s’, 0 –<< Severity 0               , 1, @time) WITH NOWAIT   

‘WAITFOR DELAY ’00:00:0’

END TRY

BEGIN CATCH

    PRINT ‘3 PRINT in the CATCH block ‘          + convert (varchar(30), getdate(), 8)   

PRINT ‘3A Error Number = ‘ +convert (VARCHAR, ERROR_NUMBER())        + ‘ Severity = ‘ + convert (varchar, ERROR_SEVERITY())        + ‘ Msg = ”’ + ERROR_MESSAGE()+””

END CATCH

PRINT ‘4 PRINT after the CATCH block ‘ + convert (varchar(30), getdate(), 8)

خروجی در اینجا نشان داده شده است:

1PRINT in the TRY block 16:03:04

2RAISERROR WITH  NOWAIT 16:03:04

3PRINT after the CATCH block 16:03:09

توجه داشته باشید که خطوط 3 و 3A در بلوک CATCH با وجود اجرای RAISERROR به آنها دسترسی پیدا نمی کند. با این حال، اگر شدت RAISERROR را به 11 تغییر دهید، این عبارت به عنوان یک خطا تلقی می شود. در اینجا اسکریپت دوباره با تغییر شدت RAISERROR آمده است:

DECLARE @time char(8)

BEGIN TRY 

   PRINT ‘1 PRINT in the TRY block ‘             + convert (varchar(30), getdate(), 8) 

   SET @time= convert (varchar(30), getdate(), 8)   

RAISERROR (‘2 RAISERROR with NOWAIT %s’, 11 –<< Severity 11               , 1, @time) WITH NOWAIT   

‘WAITFOR DELAY ’00:00:05’

END TRY

BEGIN CATCH

    PRINT ‘3 PRINT in the CATCH block ‘          + convert (varchar(30), getdate(), 8)   

PRINT ‘3A Error Number = ‘ +convert (VARCHAR, ERROR_NUMBER())        + ‘ Severity = ‘ + convert (varchar, ERROR_SEVERITY())        + ‘ Msg = ”’ + ERROR_MESSAGE()+””

END CATCH

PRINT ‘4 PRINT after the CATCH block ‘ + convert (varchar(30), getdate(), 8)

که خروجی زیر را تولید می کند:

1PRINT in the TRY block 16:11:13

2PRINT in the CATCH block 16:11:13

3A ERROR_NUMBER=50000 SEVERITY=11 msg=’2 RAISERROR WITH ‘NOWAIT 16:11:13

4PRINT after the CATCH block 16:11:13

توجه داشته باشید که عبارت RAISERROR توسط TRY/CATCH مدیریت می شود و به خودی خود خروجی پیام تولید نمی کند. در عوض، خطا توسط بلوک CATCH کنترل می شود، که دارای کدی است که پیام را در خط 3A همراه با قید شدت خطا، چاپ می کند.

برچسب ها: بدون برچسب

نظر بگذارید

آدرس ایمیل شما منتشر نخواهد شد. قسمتهای مورد نیاز علامت گذاری شده اند *