使用PowerShell重命名SQL数据库不会重命名物理文件名

时间:2013-05-30 08:26:44

标签: sql powershell

我正在创建一个可以重命名数据库的PowerShell函数。

这很有效:

    $sqlServer = "MySqlServer"
    $currentDbName = "MyDB"
    $sqlConnectionString = "Server='$sqlserver';Database='$currentDbName';Integrated Security=True"
    $sqlQueries = `
        "ALTER DATABASE [$currentDbName] SET SINGLE_USER WITH ROLLBACK IMMEDIATE",`
        "EXEC sp_renamedb '$currentDbName', '$NewName'",`
        "ALTER DATABASE [$NewName] SET MULTI_USER", `
        "ALTER DATABASE [$NewName] MODIFY FILE (NAME = $currentDbName, NEWNAME = $NewName)", `
        "ALTER DATABASE [$NewName] MODIFY FILE (NAME = $($currentDbName)_Log, NEWNAME = $($NewName)_Log)"
    $conn=new-object System.Data.SqlClient.SQLConnection($sqlConnectionString)
    try {
        $conn.Open()
        $sqlQueries | % {
            $cmd = $conn.CreateCommand()
            $cmd.CommandText = $_
            $cmd.ExecuteScalar()
            Write-Host "    Executed: $_" -ForegroundColor Gray
        }
    }
    catch{
        $actualError = $error[0]

        throw $actualError
    }
    finally{
        if($conn) {
            $conn.Close()
            $conn.Dispose()
        }
    }

此脚本重命名数据库和数据文件(假设只有一个数据文件)。

但是此脚本不会重命名文件的物理名称,也不支持重命名多个数据文件。

如何重命名数据库的物理文件?

请注意,数据库架构不在我的控制之下,我无法在数据库中添加存储过程。

[编辑] 脚本远程运行,而不是在SQL Server框中运行。

1 个答案:

答案 0 :(得分:0)

根据MSDN,您需要包含FILENAME子句

MODIFY FILE ( NAME = logical_file_name, FILENAME = ' new_path/os_file_name ' )

我相信流程将是:

  1. 重命名数据库和数据文件名称
  2. 使数据库脱机
  3. 重命名物理文件
  4. 更新数据库文件名以指向新的物理文件
  5. 将数据库重新联机
  6. 我已经开始更新您的脚本以了解我应该阅读的内容,我没有任何地方可以测试这一点,因此请确保您在“安全”的地方进行测试。

    $sqlServer = "MySqlServer"
    $currentDbName = "MyDB"
    $sqlConnectionString = "Server='$sqlserver';Database='$currentDbName';Integrated Security=True"
    
    $PhysicalLocal = "C:\Data\"
    $PhysicalUNC = "\\$sqlserver\C$\Data\"
    
    $sqlQueries = `
        "ALTER DATABASE [$currentDbName] SET SINGLE_USER WITH ROLLBACK IMMEDIATE",`
        "EXEC sp_renamedb '$currentDbName', '$NewName'",`
        "ALTER DATABASE [$NewName] SET MULTI_USER", `
        "ALTER DATABASE [$NewName] MODIFY FILE (NAME = $currentDbName, NEWNAME = $NewName)", `
        "ALTER DATABASE [$NewName] MODIFY FILE (NAME = $($currentDbName)_Log, NEWNAME = $($NewName)_Log)", `
        "ALTER DATABASE [$currentDbName] SET offline"
    
    $sqlQueriesRename = `
        "ALTER DATABASE [$NewName] MODIFY FILE (NAME = $NewName, FILENAME = $($PhysicalLocal\$NewName).mdf", `
        "ALTER DATABASE [$NewName] MODIFY FILE (NAME = $($NewName)_Log, FILENAME = $($PhysicalLocal\$NewName)_Log.ldf)", `
        "ALTER DATABASE [$currentDbName] SET online"
    
    $conn=new-object System.Data.SqlClient.SQLConnection($sqlConnectionString)
    try {
        $conn.Open()
    
        # Rename the database, leave in offline state
        $sqlQueries | % {
            $cmd = $conn.CreateCommand()
            $cmd.CommandText = $_
            $cmd.ExecuteScalar()
            Write-Host "    Executed: $_" -ForegroundColor Gray
        }
    
        # Rename the physical files
        Rename-Item $(Join-Path -Path $PhysicalUNC -ChildPath $($currentDbName).mdf) $($NewName).mdf
        Rename-Item $(Join-Path -Path $PhysicalUNC -ChildPath $($currentDbName)_Log.ldf) $($NewName)_Log.ldf
    
        # Rename the database files to match the physical ones
        $sqlQueriesRename | % {
            $cmd = $conn.CreateCommand()
            $cmd.CommandText = $_
            $cmd.ExecuteScalar()
            Write-Host "    Executed: $_" -ForegroundColor Gray
        }
    }
    catch{
        $actualError = $error[0]
        throw $actualError
    }
    finally{
        if($conn) {
            $conn.Close()
            $conn.Dispose()
        }
    }