2017-11-08 16 views
1

トランザクション内でサーバーに対してsqlファイルの内容を実行する必要があります。ファイルにはGO文で区切られたバッチが含まれているため、T-SQL TRY-CATCH ROLLBACKは実行されません。PowershellからトランザクションでGOで区切られたSQLバッチを実行する

System.Transactions.TransactionScopeと組み合わせて使用​​されていることを除いて、例外はそのトランザクションのみが中止され、有用な情報は出力されません(内部例外のチェックなし、何もありません)。

System.Data.SqlClient.SqlConnectionトランザクションをSystem.Data.SqlClient.SqlCommandと組み合わせて使用​​してみましたが、これはうまく機能しますが、GO文ではうまくいきます。

Microsoft.SqlServer.Management.Smo.Serverオブジェクトを使用する最適な解決法はありますが、私は奇妙な問題があり、すべての行を別々のバッチとして扱うことができます。

コード:

$server = New-Object Microsoft.SqlServer.Management.Smo.Server($databaseServer) 
$server.ConnectionContext.ConnectionString = $connectionString 


$script = Get-Content "$sqlScriptsPath\$scriptName.sql" 
try 
{ 
    $server.ConnectionContext.BeginTransaction() 
    $server.ConnectionContext.ExecuteNonQuery($script) 
    $server.ConnectionContext.CommitTransaction() 
} 
catch 
{ 
    $server.ConnectionContext.RollBackTransaction() 
    throw 
} 

ファイルは1行のステートメント(私は挿入でそれをテストしています)でのみ構成されている場合、それは[OK]を動作しますが、コマンドが複数行ある時はいつでも、それは何かをoutputingチョーク「不適切な構文のように」)何か、文脈に応じて。

例:スローされます

DECLARE @msg varchar(50) = 'test' 
PRINT @msg 

@msg "スカラー変数を宣言する必要があります ""。"

しかし、ファイルに ';'で区切られた両方のコマンドが1行に含まれていると、できます。

私は明らかにしようとしました:$server.ConnectionContext.BatchSeparator = 'GO'しかし、 'GO'は既にデフォルトセパレータであるため、何も変わりません。

答えて

0

私が過去にしたことは、物事のPowerShell側のステートメントを分割し、各ステートメントを個別に実行することでした。

$server = New-Object Microsoft.SqlServer.Management.Smo.Server($databaseServer) 
$server.ConnectionContext.ConnectionString = $connectionString 


$script = Get-Content "$sqlScriptsPath\$scriptName.sql" 

$ScriptArr = $script -split "GO" 

$ScriptArr | foreach { 
    try 
    { 
     $server.ConnectionContext.BeginTransaction() 
     $server.ConnectionContext.ExecuteNonQuery($_) 
     $server.ConnectionContext.CommitTransaction() 
    } 
    catch 
    { 
     $server.ConnectionContext.RollBackTransaction() 
     throw 
    } 
} 

これは、「GO」声明、およびので、分割文のことで入力コードを分割します:私がやった簡単な方法は、セパレータは、キーワードなど「GO」であるとの声明を出し分割することです分割された文字列には "GO"文が含まれません。

+0

感謝。 Hovewer、私はGOで分割する予定ですが、私はSystem.Data.SqlClient.SqlConnectionとSystem.Data.SqlClient.SqlCommandを使用しています。これははるかに一般的で堅牢です。そしてこのようにGOで分割しないでください。文字列と変数名に "GO"を付けることができます!^\ s * GO \ s *($ | \ - \ *。*)(ソース:https://stackoverflow.com/q/27301225/3922292)のような少なくとも正規表現を使用してください。 –

0

-Rawフラグを付けずに使用するコマンドレットGet-Contentは、行の配列を返します。

ソリューション:返信用

$script = Get-Content "$sqlScriptsPath\$scriptName.sql" -Raw 
関連する問題