Могу ли я печатать сразу для каждой итерации в цикле?
Мой сервер развертывания запускает развертывание script для каждой новой сборки базы данных.
Часть блоков script, чтобы ждать завершения еще одной асинхронной операции.
Код блокировки выглядит следующим образом:
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
, потому что он должен печатать обновление состояния для каждой итерации.
Сервер развертывания запускает script в sqlcmd с помощью этой команды:
sqlcmd.exe -i print_test.sql
Вывод появляется сразу:
статус 1
статус 2
статус 3
статус 4
статус 5
Он должен напечатать это через одну секунду:
статус 1
Через секунду он должен распечатать этот
статус 2
И так далее.
Есть ли способ сделать это в sqlcmd?
Ответы
Ответ 1
Вместо этого вы можете использовать osql. Он устарел, но он работает так, как вы ожидаете.
Эквивалентная команда:
osql -E -n -i print_test.sql
osql по умолчанию ожидает имя пользователя и пароль. Используйте ключ -E для использования проверки подлинности Windows. Это противоположно поведению sqlcmd по умолчанию.
osql по умолчанию печатает число для каждой строки входного файла script.
1 > 2 > 3 > 4 > 5 > 6 > 7 > 8 > 9 > 10 > 11 > 12 > 13 > 14 > 15 >
Используйте ключ -n для подавления номеров строк.
sqlcmd не имеет ключа -n. Он просто не печатает номера строк, когда установлен переключатель -i.
Мартин Смит привел меня к обходному пути, указав элемент Microsoft Connect об этой проблеме.
Если вы используете script, который использует RAISERROR WITH NOWAIT, вывод тем не менее буферизируется. Это корректно работает с OSQL и SQLCMD с SQL 2008.
Ответ 2
Есть ли способ сделать это в sqlcmd?
Не знаю, насколько я знаю.
Об этом сообщается в Connect. См. RAISERROR WITH NOWAIT, не выполняемый в SQLCMD11
SQLCMD был переписан в SQL 2012 для использования ODBC. Вот небольшой ошибка регрессии, которая, похоже, прокралась. Если вы scriptкоторый использует 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;
Ответ 3
У меня тоже была эта проблема и в предварительном порядке (с использованием вашего примера), похоже, что cmdlet-команда powershell invoke-sqlcmd не имеет такой же проблемы.
Итак, если вы можете переключить сервер развертывания на вызов powershell script, это может быть вариант.
Однако существуют некоторые ограничения invoke-sqlcmd по сравнению с sqlcmd, поэтому проверьте документы. http://msdn.microsoft.com/en-us/library/cc281720.aspx. Ваш пробег может отличаться.
Использование powershell также может упростить метод поставки sqlcmdvariable, который немного хлопотно. Хотя обычно я решил это так, чтобы я снова сломал его.