Могу ли я печатать сразу для каждой итерации в цикле?

Мой сервер развертывания запускает развертывание 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, который немного хлопотно. Хотя обычно я решил это так, чтобы я снова сломал его.