多个Invoke-SqlCmd和Sql Server事务

ca9*_*3d9 7 sql-server powershell

如何确保以下语句在一个transcation中运行?

try
{
  Invoke-SqlCmd -Query 'begin tran; ...sql script...'
  # Other Powershell script
  Invoke-SqlCmd -Query '...sql script...; if @@transcation > 0 commit tran' 
}
catch 
{
   Invoke-SqlCmd -Query 'if @@transaction > 0 rollback tran;'
}
Run Code Online (Sandbox Code Playgroud)

在事务中运行Powershell脚本的最佳方法是什么?

Nit*_*esh 8

不幸的是,SqlProvider在Powershell中没有像Registry提供者这样的交易功能.因此Start-transaction在这里不起作用.

您可以使用TransactionScope类本地并使用它.

Try{
   $scope = New-Object -TypeName System.Transactions.TransactionScope

   Invoke-Sqlcmd -server Darknite -Database AdventureWorks2008 -Query $Query1 -ea stop
   Invoke-Sqlcmd -server Darknite -Database AdventureWorks2008 -Query $Query2 -ea stop

   $scope.Complete() 
}
catch{
    $_.exception.message
}
finally{
    $scope.Dispose() 
}
Run Code Online (Sandbox Code Playgroud)

放在$ scope赋值之间的所有Invoke-sqlcmds $scope.complete()将被视为一个事务.如果其中任何一个错误,所有都将被回滚.


小智 6

Nitesh给出了一个很好的例子,帮助了我,谢谢!需要补充的一件事是 Scope.Complete() 不会将事务提交发送到数据库。如果您在循环中使用此代码,这一点将会很明显。

提交是在您的范围内最终执行的,因此确保提交的工作示例将在完成后添加显式处置,如下所示:

$scope.Complete();
$scope.Dispose();
Run Code Online (Sandbox Code Playgroud)

查看详细信息 TransactionScope Complete() 在退出 USING 语句之前不会提交事务


Cha*_*ler 4

Invoke-sqlcmd 不支持 ADO.NET 事务。您有两种解决方法,要么将等效的 Powershell 代码编写为 ADO.NET 事务的 MSDN 文档中显示的 C# 代码: http://msdn.microsoft.com/en-us/library/2k2hy99x(v=vs.110) .aspx

或者使用 T-SQL 事务。无需向每个脚本添加 T-SQL Try/Catch 即可快速执行此操作的方法是将 XACAT_ABORT 设置为 ON;然后将脚本包装在开始并提交事务中。请记住,这可能无法捕获终止错误:

http://msdn.microsoft.com/en-us/library/ms188792.aspx