3

在网上找到大量示例如何在 powershell 中执行以下操作:

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

但是,我想把它归为一个事务,所以如果其中一个 sql 文件失败,那么一切都会回滚。

我也在尝试的一种替代方法是将所有文件内容放在一个完整的脚本变量中:

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 脚本失败,整个数据库就会被锁定,就像事务无法回滚一样。我假设这与在 powershell 脚本环境中使用的 invoke-sqlcmd 而不是 Windows 命令提示符中的 sqlcmd 有关?

4

1 回答 1

1

我相信它已经解决了。在阅读了以下关于只有使用 sqlcmd 才能执行 On Error Exit 的文章后,我肯定对 powershell invoke-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 回答