【问题标题】:How to delete SQL Server databases trough vNEXT build task properly如何通过 vNEXT 构建任务正确删除 SQL Server 数据库
【发布时间】:2017-10-22 03:16:37
【问题描述】:

我们有一个用于测试机器的 PowerShell 清理脚本:

$sqlConnection = new-object system.data.SqlClient.SqlConnection("Data Source=.\SQLExpress;Integrated Security=SSPI;Initial Catalog=master")

try {

    $sqlConnection.Open()

    $commandText = @"
        exec sp_msforeachdb 'IF ''?'' NOT IN (''master'', ''model'', ''msdb'', ''tempdb'')
    BEGIN
       drop database [?]
    END'
"@  

    $sqlCommand = New-Object System.Data.SqlClient.SqlCommand
    $sqlCommand.CommandText = $commandText
    $sqlCommand.Connection = $sqlConnection
    $SQLCommand.CommandTimeout = 0
    $sqlCommand.ExecuteNonQuery()
}
finally{
    $sqlConnection.Close()
}

通常它可以工作,但有时它无法删除数据库,因为似乎有一些打开的连接并且构建任务无法删除正在使用的数据库。

这似乎也发生在“某个时候”或“随机”。

对增强脚本有何建议?

(使用最新的 TFS 2017 on prem 和 SQL Server 2014)

【问题讨论】:

    标签: sql-server powershell tfs build vnext


    【解决方案1】:

    如果您需要在没有警告的情况下切断所有用户,请在删除数据库之前将其设置为脱机。

    $commandText = @"
     exec sp_msforeachdb 'IF ''?'' NOT IN (''master'', ''model'', ''msdb'', ''tempdb'')
        BEGIN
            alter database [?] set offline with rollback immediate;drop database [?];
        END';
    "@
    

    【讨论】:

    • 感谢您的帮助,但不幸的是,如果总是失败:(Exception calling "ExecuteNonQuery" with "0" argument(s): "Option 'OFFLINE' cannot be set in database 'master'. Option 'OFFLINE' cannot be set in database 'tempdb'. Option 'OFFLINE' cannot be set in database 'model'. Option 'OFFLINE' cannot be set in database 'msdb'." At line:18 char:5 + $sqlCommand.ExecuteNonQuery() + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [], MethodInvocationException + FullyQualifiedErrorId : SqlException)
    • 您是否在运行它时使用了 if 语句包裹它?我将修改我的帖子以显示完整的$commandtext
    • 好的,我测试了几个场景。它以某种方式工作,它将数据库从管理工作室中删除,但文件仍然存在于 DATA 文件夹中,尽管出现了错误。我认为 SQL 服务仍然会查看任何数据库。尝试了不同的方法。
    【解决方案2】:

    如果在这里找到脚本:

    Drop all databases from server

    -- drops all user databases
    DECLARE @command nvarchar(max)
    SET @command = ''
    
    SELECT  @command = @command
    + 'ALTER DATABASE [' + [name] + ']  SET single_user with rollback immediate;'+CHAR(13)+CHAR(10)
    + 'DROP DATABASE [' + [name] +'];'+CHAR(13)+CHAR(10)
    FROM  [master].[sys].[databases] 
     where [name] not in ( 'master', 'model', 'msdb', 'tempdb');
    
    SELECT @command
    EXECUTE sp_executesql @command
    

    它按预期工作,仍然感谢您的帮助

    【讨论】:

      【解决方案3】:

      我可以建议使用 SMO 吗?

      push-location;
      import-module sqlps -disablenamechecking;
      pop-location
      
      $serverName = '.';
      $server = new-object microsoft.sqlserver.management.smo.server $servername;
      foreach ($db in $server.Databases | where {$_.IsSystemObject -eq $false}) {
         $server.killDatabase($db.Name);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-10-03
        • 2017-11-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-10-11
        相关资源
        最近更新 更多