При работе с T-SQL скриптами и хранимыми процедурами в SQL Server может быть сложно получить мгновенное представление о прогрессе кода. По умолчанию, операторы PRINT и вывод RAISERROR не отображаются до завершения процедуры. Однако, существует решение этой проблемы, которое позволяет получать немедленную обратную связь о прогрессе кода.
Решение заключается в использовании оператора RAISERROR с ключевым словом WITH NOWAIT. Удивительно, но для использования оператора RAISERROR не требуется наличие ошибки. Если уровень серьезности, указанный для оператора RAISERROR, находится в диапазоне от 0 до 10, SQL Server рассматривает его как обычное сообщение, а не ошибку. Выполнение продолжается с следующего оператора, даже если есть блок TRY/CATCH или если установлено значение SET XACT_ABORT ON. Сочетая уровень серьезности RAISERROR от 0 до 10 с ключевым словом WITH NOWAIT, вы можете мгновенно отправлять вывод в окно сообщений.
Вот пример использования оператора RAISERROR с ключевым словом WITH NOWAIT:
RAISERROR ('Вот это я называю сообщением!', 0, 1) WITH NOWAITИспользуя этот подход, вы можете получать обновления о прогрессе кода в режиме реального времени, не дожидаясь завершения процедуры.
Важно отметить, что при отправке результатов запроса в сетку, окно сообщений может быть скрыто. Для решения этой проблемы вы можете либо отправить результаты в текст, используя меню или CTRL+T, либо щелкнуть по окну сообщений или использовать команду меню SSMS Window/Next Pane для отображения сообщений.
Вот пример скрипта, демонстрирующего использование операторов PRINT и RAISERROR с ключевым словом WITH NOWAIT:
DECLARE @time char(8)
PRINT '1 PRINT перед всем остальным '
+ convert (varchar(30), getdate(), 8)
SET @time= convert (varchar(30), getdate(), 8)
RAISERROR ('2 RAISERROR перед WITHOUT NOWAIT %s', 0, 1, @time)
WAITFOR DELAY '00:00:05'
PRINT '3 PRINT после первой задержки '
+ convert (varchar(30), getdate(), 8)
SET @time= convert (varchar(30), getdate(), 8)
RAISERROR ('4 RAISERROR с NOWAIT %s', 0, 1, @time)
WITH NOWAIT
WAITFOR DELAY '00:00:10'
PRINT '5 PRINT после второй задержки '
+ convert (varchar(30), getdate(), 8)Выполнив этот скрипт, вы увидите результаты в окне сообщений в режиме реального времени, с каждым сообщением, появляющимся сразу после его выполнения.
Чтобы использование ключевого слова WITH NOWAIT было более удобным, вы можете создать простую хранимую процедуру, которая включает оператор RAISERROR с ключевым словом WITH NOWAIT. Эту хранимую процедуру можно выполнять всякий раз, когда вам нужно отправить немедленное сообщение вызывающей стороне.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE proc [dbo].[ns_log_nowait]
@Msg nvarchar(2047)
AS
RAISERROR (@Msg, 0, 1) WITH NOWAIT
GO
GRANT EXECUTE on [dbo].[ns_log_nowait] to PUBLIC
GOИспользуя эту хранимую процедуру, вы можете легко отправлять немедленные сообщения вызывающей стороне, не включая вручную оператор RAISERROR с ключевым словом WITH NOWAIT каждый раз.
Важно отметить, что оператор RAISERROR с уровнем серьезности менее 11 не рассматривается как ошибка в конструкции TRY/CATCH, и ключевое слово NOWAIT не влияет на это поведение. Однако, оператор RAISERROR с уровнем серьезности 0 рассматривается как оператор PRINT. Вот пример скрипта, демонстрирующего это поведение:
DECLARE @time char(8)
BEGIN TRY
PRINT '1 PRINT в блоке TRY '
+ convert (varchar(30), getdate(), 8)
SET @time= convert (varchar(30), getdate(), 8)
RAISERROR ('2 RAISERROR с NOWAIT %s', 0, 1, @time) WITH NOWAIT
WAITFOR DELAY '00:00:05'
END TRY
BEGIN CATCH
PRINT '3 PRINT в блоке CATCH '
+ convert (varchar(30), getdate(), 8)
PRINT '3A Номер ошибки = ' +convert (VARCHAR, ERROR_NUMBER())
+ ' Серьезность = ' + convert (varchar, ERROR_SEVERITY())
+ ' Сообщение = ''' + ERROR_MESSAGE() + ''''
END CATCH
PRINT '4 PRINT после блока CATCH '
+ convert (varchar(30), getdate(), 8)Выполнив этот скрипт, вы увидите, что оператор RAISERROR в блоке TRY рассматривается как оператор PRINT и не вызывает блок CATCH. Однако, если вы измените уровень серьезности оператора RAISERROR на 11, он будет рассматриваться как ошибка и вызовет блок CATCH.
Стоит отметить, что использование ключевого слова WITH NOWAIT работает в SQL Server 2000, 2005 и 2008, обеспечивая последовательное поведение в разных версиях SQL Server.
Используя ключевое слово WITH NOWAIT оператора RAISERROR, вы можете улучшить представление о прогрессе вашего кода в SQL Server. Это позволяет получать обновления и сообщения в режиме реального времени, что упрощает отладку и мониторинг ваших скриптов и хранимых процедур.