【发布时间】:2015-12-07 23:40:21
【问题描述】:
我正在尝试编写一段代码,以使用一些 Invoke-Sqlcmd 命令(由我们的系统中的错误引起)在 PowerShell 中删除和重新创建 MS SQL 数据库。我想为此建立一些应急措施,以防目标机器上的另一个程序在发出 drop 命令时正在访问数据库。我认为这样做的一个好方法是将一个 Try/Catch/Finally 命令嵌套在另一个命令中,就像这样;
$strDbName= database
$strUsername= user
$strPassword= pass
$strmdfFilePath= "C:\foo.mdf"
$strldfFilePath= "C:\bar.ldf"
Try
{
Write-Host "INFO: Attempting Database DROP command..."
Invoke-SqlCmd -Username "$strUserName" -Password "$strPassword" -Query "DROP database [$strDbName];"
}
Catch
{
Try
{
Invoke-SqlCmd -Username "$strUserName" -Password "$strPassword" -Query "ALTER database [$strDbName] set offline with ROLLBACK IMMEDIATE;"
Invoke-SqlCmd -Username "$strUserName" -Password "$strPassword" -Query "DROP database [$strDbName];"
}
Catch
{
Write-Host "Error message"
}
Finally
{
Exit
}
}
Finally
{
Invoke-SqlCmd -Username "$strUserName" -Password "$strPassword" -Query "CREATE DATABASE [$strDbName] ON (FILENAME = '$dirMdfFilePath'),(FILENAME = '$dirLdfFilePath') for ATTACH;"
}
两个问题 - A) 嵌套 Try/Catch/Finally 命令真的有效吗? B) 这种类型的命令序列是好的做法吗?我没有测试机器来尝试这个,如果有更简单的方法来执行这样的命令,我想知道。
【问题讨论】:
-
你绝对可以嵌套它们。在您的情况下,我想知道您是否可以通过事先检查表格的状态来避免它(我根本不知道该怎么做。)。那个alter命令......为什么不首先将其设置为离线?
-
嗨,马特,我确实对此进行了调查,可以通过查询数据库中的开放连接来实现。我提出的方法绝对不是做我想做的最优雅的方式,所以我可能会研究这个在程序中实施一些防御性编码的课程。
-
只是为了跟进这一点,我找到了以下信息;如果将变量设置为 Microsoft.SqlServer.Management.Smo.Server,则可以使用“GetActiveDBConnectionsCount("foobar")”方法输出当前特定数据库的连接数。
-
@Fredulom 将数据库设置为
offline状态可能会相当缓慢且占用大量资源。我认为更好的选择是使用set single_user,断开其他所有人的连接并回滚任何未提交的事务(= 一样安全,但速度更快)。不过仍然会立即回滚