3

PowerShellで次のことを行う方法の例がオンラインでたくさん見つかりました:

Get-ChildItem $databaseFolder -Filter *.sql -Recurse | ForEach-Object { sqlcmd -S  $databaseServer -d $databaseName -E -i $_.FullName } 

ただし、これを 1 つのトランザクションにグループ化したいので、SQL ファイルの 1 つが失敗した場合、すべてがロールバックされます。

私が試している代替手段の 1 つは、すべてのファイルの内容を完全なスクリプト変数にまとめることです。

foreach( $file in Get-ChildItem -path $databaseFolder -Filter *.sql | sort-object )
{
    Get-Content $file.fullName | Foreach-Object { $fullSqlScript = $fullSqlScript + $_ + "`n" } ;
}

そして、最後に次のように実行します。

 invoke-sqlcmd -ServerInstance $databaseServer -Database $databaseName -Query $fullSqlScript | format-table | out-file -filePath $outFile

$fullSqlScript には、先頭に次のコードも挿入されます。

:On Error Exit
 SET XACT_ABORT ON
 GO
 Begin Transaction

そして終わり:

IF XACT_STATE() = 1
BEGIN
    PRINT 'Committing Transaction...'
    COMMIT TRANSACTION
END
ELSE IF XACT_STATE() = -1
BEGIN
    PRINT 'Scripts Failed... Rolling back'
    ROLLBACK TRAN
END

ただし、意図的なSQLスクリプトを失敗させるとすぐに、トランザクションをロールバックできないようにデータベース全体がロックされます。これは、Windowsコマンドプロンプトからのsqlcmdではなく、powershellスクリプト環境で使用されているinvoke-sqlcmdと関係があると思いますか?

4

1 に答える 1

1

私はそれが解決されたと信じています。On Error Exitがsqlcmdを使用してのみ実行できるようにすることについての次の記事を読んだ後、私は間違いなくpowershellinvoke-sqlcmdについて疑問を持っていました。

ここで私が見つけたいくつかのドキュメントは、それと関係があると思います: http ://technet.microsoft.com/en-us/library/cc281720.aspx

特に以下:*

すべてのsqlcmdコマンドがInvoke-Sqlcmdに実装されているわけではありません。実装されていないコマンドには、:!!、:connect、:error、:out、:ed、:list、:listvar、:reset、:perftrace、および:serverlistが含まれます。

*

結局、私はまだ各ファイルの内容を読み取らなければならないという戦略を使用していて、それから:

:On Error Exit

他のファイルからの他のすべてのSQLを含む出力ファイルに最終的に書き込まれるスクリプトの先頭。

次に、実際のsqlcmdを呼び出すために次のようにします。

$command = "sqlcmd.exe -S " + $databaseServer + " -d " + $databaseName + " -i " + $outFile
Invoke-Expression $command

これは問題なく機能しているようで、すべてがロールバックされます:)誰かがより良い解決策を考えられるなら、私に知らせてください!

于 2012-09-19T23:27:44.117 に答える