Как сделать SSDT Profile.xml SqlCmdVariable пустой строкой или необязательной

Я использую SSDT (и sqlproj) для наших проектов MSSQL. У нас есть несколько переменных, которые нам нужно установить при публикации в каждой среде.

Это прекрасно работает в большинстве наших сред, где мы присваиваем значения всем переменным, но когда мы публикуем в нашей действующей базе данных, я хотел бы иметь возможность сделать DomainPrefix пустой строкой.

Когда я пытаюсь изменить Live.profile.xml, чтобы установить значение DomainPrefix, я получаю сообщение об ошибке: «Произошла ошибка во время создания плана развертывания. Невозможно продолжить развертывание. Отсутствуют значения для следующих переменных SqlCmd: DomainPrefix».

Вот как я хотел бы, чтобы Live.profile.xml выглядел так:

<?xml version="1.0" encoding="UTF-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="12.0">
  <PropertyGroup>
    <TargetDatabaseName>DB_NAME</TargetDatabaseName>
    <DeployScriptFileName>DB_NAME.sql</DeployScriptFileName>
    <TargetConnectionString>CONNECTION_STRING</TargetConnectionString>
    <ProfileVersionNumber>1</ProfileVersionNumber>
  </PropertyGroup>
  <ItemGroup>
    <SqlCmdVariable Include="DomainPrefix">
      <Value></Value>
    </SqlCmdVariable>
    <SqlCmdVariable Include="Environment">
      <Value>live</Value>
    </SqlCmdVariable>
  </ItemGroup>
</Project>

Кто-нибудь знает, как установить для SqlCmdVariable пустое значение или сделать его необязательной переменной?

С использованием:

  • VS 2013 sqlproj
  • SqlPackage.exe для запуска публикации в БД из командной строки

person Saan    schedule 20.04.2015    source источник
comment
Как вы используете DomainPrefix? Является ли это частью сценариев Pre/Post, используемых в объектах/коде, именах серверов, чем-то еще? Если вы используете это только для сценариев Pre/Post, вы можете соответствующим образом манипулировать этими сценариями с помощью раздела для производства, который немного отличается.   -  person Peter Schott    schedule 21.04.2015
comment
DomainPrefix специально используется в пост-скрипте, и у нас есть некоторый код для его обработки, но это также одна из нескольких переменных, которые мы хотим установить как пустую строку, поэтому было бы неплохо узнать, есть ли способ сделать это пусто/опционально.   -  person Saan    schedule 21.04.2015
comment
Я не знаю, как это сделать, поэтому я хотел убедиться, что вы используете его только в сценарии Post. Вы можете проверить какое-либо значение (например, Prod) и сделать его пустым, если это так, и/или создать раздел для производства. Я думаю, что MS никогда не рассматривает пустую переменную, потому что это может привести к хаосу, если использовать его в коде, особенно для имен БД.   -  person Peter Schott    schedule 21.04.2015
comment
Я не думаю, что есть простой вариант, если только вы не начнете взламывать его, подробнее читайте здесь: blogs.msdn.com/b/sql_server_appendix_z/archive/2013/02/23/   -  person Eugene Niemand    schedule 01.05.2015
comment
@PeterSchott и Saan, я опубликовал ответ, который должен решить проблему, и для двух разных интерпретаций того, как эта переменная будет использоваться.   -  person Solomon Rutzky    schedule 18.08.2015
comment
@EugeneNiemand Это определенно правильное мышление. Однако, к большому сожалению, большинство команд SQLCMD запрещены вне выполнения сценария SQL через SQLCMD.EXE. Только небольшое подмножество доступно для режима SQLCMD в SSMS / Visual Studio (с :out и обстрелом через !! не), и я не верю, что все они доступны через публикацию SSDT. Я разместил ответ ниже с лучшим, что я мог придумать, учитывая ограничения.   -  person Solomon Rutzky    schedule 18.08.2015


Ответы (1)


Кажется, нет никакого способа передать строку NullOrWhiteSpace как SqlCmdVariable. Основной синтаксис для SqlCmdVariable:

<SqlCmdVariable Include="DomainPrefix">
  <DefaultValue>
  </DefaultValue>
  <Value></Value>
</SqlCmdVariable>

Либо Value, либо DefaultValue должны иметь некоторое значение, отличное от пробела.

Итак, для вашего первого варианта, как предложил @Peter в комментарии к вопросу, вы можете обработать это в своем сценарии SQL после развертывания, проверив определенное значение, например <Live> или что-то еще. Сделайте что-то вроде следующего:

DECLARE @DomainPrefix NVARCHAR(50) = N'$(DomainPrefix)';

IF (@DomainPrefix = N'<Live>')
BEGIN
  SET @DomainPrefix = '';
END;

А затем просто соедините @DomainPrefix со строками вместо включения в них $(DomainPrefix).

Конечно, если вам нужно, чтобы переменная SQLCMD была доступна в основном контексте T-SQL, а не только как переменная T-SQL (например, если вы используете ее в качестве префикса связанного сервера или базы данных в строках UPDATE $(DomainPrefix)[DatabaseName].[dbo].[TableName]..., где $(DomainPrefix) обычно определяется как [LinkedServerName]. ), тогда вы сможете избежать использования Value из /**/ (или даже /* Live */ ), чтобы результирующий T-SQL интерпретировался как:

UPDATE [LinkedServerName].[DatabaseName].[dbo].[TableName]...

or:

UPDATE /* Live */[DatabaseName].[dbo].[TableName]...

оба из них являются действительными T-SQL и работают. Итак, в этом случае вы должны использовать следующее:

<SqlCmdVariable Include="DomainPrefix">
  <Value>/* Live */</Value>
</SqlCmdVariable>
person Solomon Rutzky    schedule 18.08.2015
comment
Умный, и я вижу, как это может обойти вашу проблему. Это одна из причин, по которой я пытался выяснить, где вы использовали переменную и с какой целью. :) - person Peter Schott; 19.08.2015
comment
@PeterSchott Спасибо :-) . Но я не ОП ;-) - person Solomon Rutzky; 19.08.2015