Как очистить буфер PRINT в TSQL?

У меня есть очень долго выполняющаяся хранимая процедура в SQL Server 2005, которую я пытаюсь отлаживать, и для этого я использую команду print. Проблема в том, что я получаю сообщения от SQL Server только в самом конце моего sproc - я хотел бы иметь возможность очистить буфер сообщений и сразу увидеть эти сообщения во время выполнения sproc, а не в самом конце конец.

Небольшое замечание для людей, которые (как и я) думают, что ответы для них не работают: не забудьте переключиться на вкладку «Сообщения», когда выполняется запрос. По умолчанию вы увидите вкладку «Результаты».

Tomasz Gandor 18.11.2019 09:29
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
233
1
101 379
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Ответ принят как подходящий

Используйте функцию RAISERROR:

RAISERROR( 'This message will show up right away...',0,1) WITH NOWAIT

Не стоит полностью заменять все свои отпечатки на raiserror. Если у вас где-то есть цикл или большой курсор, просто делайте это один или два раза за итерацию или даже каждые несколько итераций.

Также: я впервые узнал о RAISERROR по этой ссылке, которую я теперь считаю исчерпывающим источником по обработке ошибок SQL Server и определенно заслуживающим внимания:
http://www.sommarskog.se/error-handling-I.html

Обратите внимание, что TRY / CATCH в SQL будет отлавливать только ошибки с серьезностью> 10, поэтому использование RAISERROR таким образом не перейдет в ваш оператор CATCH. И это здорово, так как это означает, что вы все еще можете использовать RAISERROR таким образом с TRY / CATCH. ссылка: msdn.microsoft.com/en-us/library/ms175976.aspx

Rory 13.04.2011 02:24

Обратите внимание, что это не работает после первых 500 сообщений; как только вы печатаете больше, он внезапно начинает буферизоваться!

GendoIkari 10.09.2015 23:51

@MahmoudMoravej Нет, я все еще запускаю длительные процессы, используя RAISEERROR, и просто имею дело с тем фактом, что через некоторое время сообщения начинают буферизоваться. Похоже, единственное решение - использовать другой инструмент, отличный от SSMS.

GendoIkari 13.10.2015 16:31

Я думаю, что это кое-что изменилось в последней версии SS. Когда я впервые написал это, мы использовали RAISERROR для обширного протоколирования ночных пакетных процессов с более чем 500 сообщениями, и это не было проблемой. Но за 7 лет многое может измениться.

Joel Coehoorn 13.10.2015 17:29

Некоторые подробности в этом q stackoverflow.com/questions/20608989/…, почему это не работает в sqlcmd в последних версиях

Lanorkin 05.05.2016 11:40

По уведомлению @GendoIkari. Я пробовал с ssms от 2016SP1 с этим скриптом. На 500 он переключается на буферизацию 50 строк, а на 1k он переключается на 100 строк каждая. Так продолжалось как минимум до 2к, но потом я остановил скрипт. объявить @i int set @i = 0 объявить @t varchar (100), а 1 = 1 начать набор @i = @i + 1 set @t = 'print' + convert (varchar, @i) RAISERROR (@t, 10 , 1) С NOWAIT ждать окончания задержки '00: 00: 00.010 '

Zartag 08.08.2017 18:11

Да ... Первый параметр функции RAISERROR требует переменной NVARCHAR. Итак, попробуйте следующее;

-- Replace PRINT function
DECLARE @strMsg NVARCHAR(100)
SELECT @strMsg = 'Here''s your message...'
RAISERROR (@strMsg, 0, 1) WITH NOWAIT

ИЛИ ЖЕ

RAISERROR (n'Here''s your message...', 0, 1) WITH NOWAIT

Посмотрите на вкладку «Сообщения» внизу, рядом с вкладкой «Результаты», или переключитесь в режим «Результаты в текст».

Mehmet Ergut 19.01.2011 12:48

Чтобы переключиться в режим «Результаты в текст», в SSMS выберите «Сервис» -> «Параметры» -> «Результаты запроса» -> SQL Server -> «Общие» -> «Место назначения по умолчанию для результатов» и выберите «Результаты в текст» вместо «Результаты в сетки», повторно -откройте окно запроса, и тогда вы не будете сидеть и смотреть на пустую вкладку результатов, как на пустышку, в то время как вывод RAISERROR переходит на вкладку сообщений.

Adam 09.02.2017 17:19

Для справки: если вы работаете в скриптах (пакетная обработка), а не в хранимой процедуре, вывод промывки запускается командой GO, например

print 'test'
print 'test'
go

В общем, мой вывод следующий: вывод выполнения сценария mssql, выполняемого в графическом интерфейсе пользователя SMS или с помощью sqlcmd.exe, сбрасывается в файл, stdoutput, окно графического интерфейса при первом операторе GO или до конца сценария.

Очистка внутри хранимой процедуры работает по-другому, так как вы не можете поместить GO внутрь.

Ссылка: инструкция tsql Go

go не просто сбрасывает вывод, он завершает пакет в соответствии с предоставленной вами ссылкой. Все, что у вас declared, отбрасывается, поэтому не очень удобно для отладки. declare @test int print "I want to read this!" go set @test=5 выдает ошибку, утверждая, что @test не определен, потому что он находится в новой партии.
asontu 21.09.2015 16:10

Я согласен, это неправильный ответ на этот вопрос, но я поставил ответ (см. Отказ от ответственности в начале), поскольку он может быть полезен для кого-то другого - например, кто-то, кто запускает пакетный sql.

Robert Lujo 21.09.2015 19:54

Другой лучший вариант - не зависеть от PRINT или RAISERROR и просто загрузить свои операторы print в таблицу ## Temp в TempDB или в постоянную таблицу в вашей базе данных, которая сразу же предоставит вам видимость данных с помощью оператора SELECT из другого окна. . Это работает лучше всего для меня. Использование постоянной таблицы также служит журналом того, что произошло в прошлом. Операторы печати удобны для ошибок, но с помощью таблицы журнала вы также можете определить точную точку отказа на основе последнего зарегистрированного значения для этого конкретного выполнения (при условии, что вы отслеживаете общее время начала выполнения в таблице журнала).

Это может быть проблемой, если вы пишете действительно транзакционный сценарий с фиксацией и откатом. Я не верю, что вы сможете запросить свою временную таблицу вживую - и она исчезнет, ​​если ваша транзакция не удастся.

SteveJ 04.11.2016 21:59

@SteveJ, вы можете запросить его вживую, используя SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; в сеансе мониторинга

TheConstructor 07.12.2016 12:59

@TheConstructor; Это полезный совет - я воспользуюсь им, спасибо. Однако разве мы все еще не остались с временной таблицей, уходящей при откате? Если проводить анализ отказов, это будет большим недостатком.

SteveJ 07.12.2016 21:15

@SteveJ Да, конечно, это есть. Конечно, вы можете скопировать данные из транзакции READ UNCOMMITTED в другую таблицу, но вы, вероятно, упустите момент непосредственно перед ROLLBACK. Так что это, вероятно, решает вопрос «как далеко?» а не «почему откат?»

TheConstructor 07.12.2016 21:21

Основываясь на ответе @JoelCoehoorn, мой подход состоит в том, чтобы оставить все мои операторы PRINT на месте и просто следовать им оператором RAISERROR, чтобы вызвать сброс.

Например:

PRINT 'MyVariableName: ' + @MyVariableName
RAISERROR(N'', 0, 1) WITH NOWAIT

Преимущество этого подхода в том, что операторы PRINT могут объединять строки, тогда как RAISERROR - нет. (Так что в любом случае у вас есть такое же количество строк кода, сколько вам нужно будет объявить и установить переменную для использования в RAISERROR).

Если, как и я, вы используете AutoHotKey или SSMSBoost или аналогичный инструмент, вы можете легко настроить ярлык, такой как «] flush», чтобы ввести за вас строку RAISERROR. Это экономит ваше время, если это одна и та же строка кода каждый раз, то есть ее не нужно настраивать для хранения определенного текста или переменной.

Обратите внимание, что RAISERROR() поддерживает строковую интерполяцию в стиле printf(). Например, если @MyVariableName является строковым типом (например, VARCHAR(MAX), NVARCHAR(MAX) и т. д.), Вы можете использовать RAISERROR() с одной строкой: RAISERROR(N'MyVariableName: %s', 0, 1, @MyVariableName).

binki 24.07.2018 01:18

Это так удобно! Я знаю, что RAISERROR может выполнять простую замену, но попробуйте заменить время [дата] или вызвать функцию из оператора RAISERROR! Этот ответ дает вам простой FLUSH в форме появления пустой ошибки (за счет новой строки).

Tomasz Gandor 18.11.2019 09:26

Другие вопросы по теме