Можно ли печатать сразу для каждой итерации в цикле?
Мой сервер развертывания запускает сценарий развертывания для каждой новой сборки базы данных.
Часть скрипта блокирует ожидание завершения другой асинхронной операции.
Код блокировки выглядит следующим образом:
DECLARE @i INT = 0;
DECLARE @laststatus NVARCHAR(MAX) = N'';
WHILE @i < 5
BEGIN
-- the real delay is longer
WAITFOR DELAY '00:00:01';
-- poll async operation status here
SET @i = @i + 1;
SET @laststatus = N'status is ' + CAST(@i AS NVARCHAR(MAX));
RAISERROR(@laststatus, 0, 1) WITH NOWAIT;
END;
Он использует WITH NOWAIT
пункт о RAISERROR
вместо PRINT
потому что он должен печатать обновление статуса для каждой итерации.
Сервер развертывания запускает сценарий в sqlcmd с помощью этой команды:
sqlcmd.exe -i print_test.sql
Выходные данные появляются сразу, как это:
статус 1
статус 2
статус 3
статус 4
статус 5
Это должно напечатать это через одну секунду:
статус 1
Еще через секунду он должен напечатать это
статус 2
И так далее.
Есть ли способ сделать это в sqlcmd?
3 ответа
Вместо этого вы можете использовать osql. Это устарело, но работает так, как вы ожидаете.
Эквивалентная команда:
osql -E -n -i print_test.sql
osql по умолчанию ожидает имя пользователя и пароль. Используйте ключ -E для использования аутентификации Windows. Это противоположно поведению по умолчанию sqlcmd.
По умолчанию osql печатает число для каждой строки в скрипте входного файла.
1> 2> 3> 4> 5> 6> 7> 8> 9> 10> 11> 12> 13> 14> 15>
Используйте ключ -n для подавления номеров строк.
У sqlcmd нет ключа -n. Он просто не печатает номера строк, когда установлен ключ -i.
Мартин Смит привел меня к обходному пути, процитировав пункт Microsoft Connect об этой проблеме.
Если вы используете скрипт, который использует RAISERROR WITH NOWAIT, вывод тем не менее буферизуется. Это работает правильно с OSQL и SQLCMD из SQL 2008.
Есть ли способ сделать это в sqlcmd?
Не так далеко, как я знаю.
Об этом уже сообщалось в Connect. Посмотрите, что RAISERROR WITH NOWAIT не соблюдается в SQLCMD11
SQLCMD был переписан в SQL 2012 для использования ODBC. Вот небольшая ошибка регрессии, которая, кажется, проникла внутрь. Если у вас скрипт, который использует RAISERROR WITH NOWAIT, вывод, тем не менее, буферизуется. Это работает правильно с OSQL и SQLCMD из SQL 2008.
но в настоящее время не исправлено.
Я полагаю, вы могли бы добавить SELECT
там есть размер вашего сетевого пакета (или увеличьте существующий размер сообщения), чтобы очистить буфер в качестве обходного пути.
Например
DECLARE @i INT = 0;
WHILE @i < 5
BEGIN
-- poll async operation status here
SET @i = @i + 1;
PRINT 'status is ' + CAST(@i AS VARCHAR(10)) + SPACE(4000);
WAITFOR DELAY '00:00:01';
END;
У меня тоже была эта проблема, и предварительно (на вашем примере) может показаться, что у командлета powershell invoke-sqlcmd такой же проблемы нет.
Так что, если вы можете вместо этого переключить свой сервер развертывания на вызов сценария powershell, это может быть вариантом.
Однако есть некоторые ограничения invoke-sqlcmd по сравнению с sqlcmd, поэтому проверьте документы. http://msdn.microsoft.com/en-us/library/cc281720.aspx. Ваш пробег может отличаться.
Использование powershell также может упростить метод предоставления sqlcmdvariable, что немного проблематично... хотя обычно я уже решил это, поэтому я собираюсь все это снова сломать.