web-dev-qa-db-ja.com

SQLCMDを使用したPostDeployment.sqlスクリプトの条件付きロジック

SQL 2008データベースプロジェクト(Visual Studio)を使用して、プロジェクトのスキーマと初期テストデータを管理しています。 atabaseプロジェクトは、SQLCMDの ":r"構文を使用する他の多くのスクリプトを含む展開後を使用します。

SQLCMD変数に基づいて特定のファイルを条件付きで含めることができるようにしたいと思います。これにより、ナイトリービルドを使用してプロジェクトを数回実行し、さまざまなバージョンのデータベース(マルチテナントシステム用)を使用してデータベースのさまざまなバージョンをセットアップできます。

私は次を試しました:

IF ('$(ConfigSetting)' = 'Configuration1')
  BEGIN
    print 'inserting specific configuration' 
:r .\Configuration1\Data.sql
  END
ELSE
  BEGIN
    print 'inserting generic data' 
:r .\GenericConfiguration\Data.sql
  END

しかし、コンパイルエラーが表示されます:SQL01260:致命的なパーサーエラーが発生しました:Script.PostDeployment.sql

誰かがこのエラーを見たか、このように柔軟に展開後のスクリプトを構成できましたか?または、私はこれについて完全に間違った方法で行っていますか?

ありがとう、ロブ

追伸また、ファイルへのパスが変数になるようにこれを変更しようとしました この投稿に似ています 。しかし、これはパスが間違っているというエラーを表示します。

52
Rob Bird

[〜#〜] update [〜#〜]

リンクされたスクリプトの一部にGOステートメントが必要なため、上記のif/else構文が機能しないことがわかりました。基本的に:rはスクリプトをインラインでインポートするだけなので、これは無効な構文になります。

リンクされたスクリプトにGOステートメントが必要な場合(私と同じように)、これを回避する簡単な方法はありません。結局、いくつかのポストデプロイメントスクリプトを作成し、ビルド時に主なポストデプロイメントスクリプトを上書きするようにプロジェクトを変更することになりましたビルド構成。これで必要なことはできましたが、もっと簡単な方法があるはずです!

同じことを必要とする人のために- 私はこの投稿が有用であることがわかった

したがって、私のプロジェクトには、次の展開後ファイルがあります。

  • Script.PostDeployment.sql(置き換えられる空のファイル)
  • Default.Script.PostDeployment.sql(標準のデータ設定に必要なスクリプトへのリンク)
  • Configuration1.Script.PostDeployment.sql(特定のデータ構成に必要なスクリプトへのリンク)

次に、プロジェクトファイルの最後に以下を追加しました(右クリックしてアンロードしてから、右クリックして編集します)。

  <Target Name="BeforeBuild">
      <Message Text="Copy files task running for configuration: $(Configuration)" Importance="high" />
      <Copy Condition=" '$(Configuration)' == 'Release' " SourceFiles="Scripts\Post-Deployment\Default.Script.PostDeployment.sql" DestinationFiles="Scripts\Post-Deployment\Script.PostDeployment.sql" OverwriteReadOnlyFiles="true" />
      <Copy Condition=" '$(Configuration)' == 'Debug' " SourceFiles="Scripts\Post-Deployment\Default.Script.PostDeployment.sql" DestinationFiles="Scripts\Post-Deployment\Script.PostDeployment.sql" OverwriteReadOnlyFiles="true" />
      <Copy Condition=" '$(Configuration)' == 'Configuration1' " SourceFiles="Scripts\Post-Deployment\Configuration1.Script.PostDeployment.sql" DestinationFiles="Scripts\Post-Deployment\Script.PostDeployment.sql" OverwriteReadOnlyFiles="true" />
  </Target>

最後に、ソリューションで一致するビルド構成をセットアップする必要があります。

また、他の回避策を試している人のために、次のことも運なしで試しました:

  1. プロジェクトファイルXMLをハッキングする代わりに、ファイルをコピーするためのビルド後イベントを作成します。展開後のスクリプトファイルへの正しいパスを作成できなかったため、これを機能させることができませんでした。 この接続の問題は問題を説明しています

  2. スクリプトパスに変数を使用して、:rコマンドに渡します。しかし、このアプローチにはいくつかのエラーがありました。

36
Rob Bird

noexec method を使用して問題を回避できました。

したがって、これの代わりに:

IF ('$(ConfigSetting)' = 'Configuration1')
 BEGIN
    print 'inserting specific configuration' 
    :r .\Configuration1\Data.sql
 END

条件を逆にして、NOEXEC ONを設定して、インポートされたステートメントをスキップします。

IF ('$(ConfigSetting)' <> 'Configuration1')
    SET NOEXEC ON

:r .\Configuration1\Data.sql

SET NOEXEC OFF

後続のステートメントを実行する場合は、必ずオフにしてください。

18
Simon Calvin

リリース後の構成ではなく、デバッグ用のテストデータを展開するために、展開後プロセス内で条件付き展開を処理する方法を次に示します。

まず、ソリューションエクスプローラーでプロジェクトプロパティフォルダーを開き、右クリックして新しいSqlCmd.variablesファイルを追加します。

ファイルに_Debug.sqlcmdvars_という名前を付けます。

ファイル内にカスタム変数を追加し、$(BuildConfiguration)という最終変数を追加して、値をDebugに設定します。

$(BuildConfiguration)をReleaseに設定して、Release.sqlcmdvarsを作成するプロセスを繰り返します。

次に、構成を構成します。プロジェクトのプロパティページを開き、[展開]タブを開きます。上部のドロップダウンで、構成をデバッグに設定します。一番下のドロップダウン(Sqlコマンド変数)で、ファイルをProperties\Debug.sqlcmdvarsに設定します。

次のリリースとして繰り返します:上部のドロップダウンで、構成をリリースに設定します。下部のドロップダウン(Sqlコマンド変数)で、ファイルをProperties\Release.sqlcmdvarsに設定します。

これで、Script.PostDeployment.sqlファイル内で、次のような条件付きロジックを指定できます。

_IF 'Debug' = '$(BuildConfiguration)'
BEGIN
PRINT '***** Creating Test Data for Debug configuration *****';
:r .\TestData\TestData.sql
END
_

ソリューションエクスプローラーで、最上位のソリューションを右クリックし、構成マネージャーを開きます。ビルドでアクティブにする構成を指定できます。 MSBUILD.EXEコマンドラインで構成を指定することもできます。

開発者ビルドにはテストデータがありますが、リリースビルドはありません!

15
Rob McCauley

Robがうまくいったため、リンクされたSQLスクリプトではGOステートメントを使用できません。これにより、BEGIN/ENDステートメント内に入れ子になります。

ただし、彼には別の解決策があります-可能であれば、参照されているスクリプトからGOステートメントを削除し、ENDステートメントの後に単一のステートメントを配置します。

IF '$(DeployTestData)' = 'True'
BEGIN
    :r .\TestData\Data.sql
END
GO -- moved from Data.sql

sqlcmdvarsファイルに$(DeployTestData)という名前の新しい変数を作成したことに注意してください。これにより、テストスクリプトの展開をオンまたはオフにできます。

8
Dunc

MSDNブログのハック が見つかりましたが、これはかなりうまくいきました。秘Theは、コマンドを一時スクリプトファイルに書き込み、代わりにそのスクリプトを実行することです。基本的に、SQLCMDの動的SQLと同等です。

_-- Helper newline variable
:setvar CRLF "CHAR(13) + CHAR(10)"
GO
-- Redirect output to the TempScript.sql file
:OUT $(TEMP)\TempScript.sql

IF ('$(ConfigSetting)' = 'Configuration1')
  BEGIN
    PRINT 'print ''inserting specific configuration'';' + $(CRLF)   
    PRINT ':r .\Configuration1\Data.sql' + $(CRLF)
  END
ELSE
  BEGIN
    PRINT 'print ''inserting generic data'';' + $(CRLF) 
    PRINT ':r .\GenericConfiguration\Data.sql' + $(CRLF)
  END
GO
-- Change output to stdout
:OUT stdout

-- Now execute the generated script
:r $(TEMP)\TempScript.sql
GO
_

_TempScript.sql_ファイルには次のいずれかが含まれます。

_print 'inserting specific configuration';   
:r .\Configuration1\Data.sql
_

または

_print 'inserting generic data';
:r .\GenericConfiguration\Data.sql
_

$(ConfigSetting)の値に応じて、実行時にGOステートメントなどに問題はありません。

2
kjbartel

ロブ・バードのソリューションに触発されました。ただし、ビルドイベントを使用して、選択したビルド構成に基づいて展開後のスクリプトを置き換えるだけです。

  1. 空の「ダミー」ポストデプロイメントスクリプトが1つあります。
  2. ビルド前イベントを設定して、選択したビルド構成に基づいてこの「ダミー」ファイルを置き換えます(添付の図を参照)。
  3. ビルドが完了した後に「ダミー」ファイルを戻すために、ビルド後イベントを設定しました(添付の図を参照)。理由は、ビルド後に変更管理で変更を生成したくないからです。

Build Events setup example

2
Martin Karouš