使用PowerShell和SMO库从.BAK文件创建新数据库

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用PowerShell和SMO库从.BAK文件创建新数据库相关的知识,希望对你有一定的参考价值。

我正在尝试使用powershell从.bak文件创建一个新的SQL Server数据库。

这是我的脚本:

TRY
{
    [System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.SMO') | out-null 
    [System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.SmoExtended') | out-null
    $servername = "MyServerMyServerInstance"
    $datapath= "E:SQLDataMyNewDataBase"
    $logpath= "E:SQLLogsMyNewDataBase"
    $path= "\MyServerBKPFolder"
    $server = new-object("Microsoft.SqlServer.Management.Smo.Server") $servername
    $folderitem=Get-ChildItem $path -filter *.bak -rec

    foreach($bkfiles in $folderitem)
    {
        $dbRestore = new-object("Microsoft.SqlServer.Management.Smo.Restore")
        $files = $path+$bkfiles.Name
        $backupFile = $files
        $dbRestore.Devices.AddDevice($backupFile, [Microsoft.SqlServer.Management.Smo.DeviceType]::File)
        $dbRestoreDetails = $dbRestore.ReadBackupHeader($server)
        $dbFileList= $dbRestore.ReadFileList($server)

        foreach ($row in $dbFileList)
        {
             $FileType = $row["Type"].ToUpper()

             If ($FileType.Equals("D")) 
             {
                 $DBLogicalName = $Row["LogicalName"]
             }

             ELSEIf ($FileType.Equals("L")) 
             {
                 $LogLogicalName = $Row["LogicalName"]
             }
        }

        $dbRestoreFile = new-object("Microsoft.SqlServer.Management.Smo.RelocateFile") 
        $dbRestoreLog = new-object("Microsoft.SqlServer.Management.Smo.RelocateFile")

        $dbRestoreFile.LogicalFileName = $DBLogicalName 
        $dbRestoreFile.PhysicalFileName =$datapath +  "" + $DBLogicalName + ".mdf" 

        $dbRestoreLog.LogicalFileName =   $LogLogicalName 
        $dbRestoreLog.PhysicalFileName =  $logpath +  "" + $LogLogicalName + ".ldf" 

        $dbRestore.RelocateFiles.Add($dbRestoreFile) 
        $dbRestore.RelocateFiles.Add($dbRestoreLog)                

        $dbRestore.Database = "MyNewDataBase"
        $dbRestore.NoRecovery = $false
        $dbRestore.Action = "DataBase"
        $dbRestore.FileNumber = 1;
        $dbRestore.ReplaceDatabase = $false;

        $dbRestore.SqlRestore($server)  
   }
} catch     {
    "Database restore failed:`n`n " + _.Exception.GetBaseException().Message
}

当我运行此代码时,我收到此错误:

文件“E: SQLData MyNewDataBase OLDDataBase_Data.mdf”的目录查找失败,出现操作系统错误2(系统找不到指定的文件。)。

文件'OLDDataBase_Data'无法还原为'E: SQLData MyNewDataBase OLDDataBase_Data.mdf'。使用WITH MOVE标识文件的有效位置。

在规划RESTORE语句时发现了问题。以前的消息提供详情。 RESTORE DATABASE异常终止。

看起来我的脚本试图从旧数据库中找到.mdf.ldf文件。但我只是从旧数据库中获得了一个.bak文件。

我错过了什么?

谢谢。

答案

经过大量的研究和尝试,我终于恢复了我的数据库。这对我有用:

[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") | Out-Null
    [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SmoExtended") | Out-Null
    [Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.ConnectionInfo") | Out-Null
    [Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SmoEnum") | Out-Null                              

    #Define o novo local dos arquivos de mdf e ldf
    $RelocateData = New-Object Microsoft.SqlServer.Management.Smo.RelocateFile("OldDataBase_Data", "E:SQLDataMyNewDataBase_DATA.mdf")
    $RelocateLog = New-Object Microsoft.SqlServer.Management.Smo.RelocateFile("OldDataBase_Log", "E:SQLLogsMyNewDataBase_LOG.ldf")

    #Executa a restauração
    Restore-SqlDatabase -ServerInstance "MyServerMyServerInstance" -Database "MyNewDataBase" -BackupFile "\BackupFolderOldDataBase.bak" -RelocateFile @($RelocateData,$RelocateLog) -NoRecovery
    Restore-SqlDatabase -ServerInstance "MyServerMyServerInstance" -Database "MyNewDataBase" -BackupFile "\BackupFolderOldDataBase.trn" -RestoreAction Log -NoRecovery 
另一答案

希望这是你需要的:

function Restore-MsSqlDatabase {
<#
.Synopsis
  Restore MSSQL database using Microsoft.SQLServer.Management.Smo.{BackupDeviceItem,Restore,RelocateFile}
.Description
  Restore MSSQL database using Microsoft.SQLServer.Management.Smo.{BackupDeviceItem,Restore,RelocateFile}
.Example
  Restore-MsSqlDatabase -BackupFile 'D:ackupsaateam_20491005.bak' -Verbose
.Example
  Restore-MsSqlDatabase -BackupFile 'D:ackupsaateam_20491005.bak' -SqlHost SQL-SERVER001 -Verbose
#>
  [CmdletBinding()]
  Param(
    [Parameter(Position=0)] [ValidateNotNullOrEmpty()]
    [string]$BackupFile,
    [Parameter(Position=1)] [ValidateNotNullOrEmpty()]
    [string]$SqlHost="localhost"
  )
  Begin{
    Write-Verbose ("$(Get-Date) - INFO - Load assembly for Microsoft.SqlServer.SMO")
    $null=[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO")
    Write-Verbose ("$(Get-Date) - INFO - Load assembly for Microsoft.SqlServer.SMOExtended")
    $null=[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMOExtended")
    Write-Verbose ("$(Get-Date) - INFO - New connection object")
    $MsSqlConnection=New-Object Microsoft.SqlServer.Management.Smo.Server $SqlHost
    Write-Verbose ("$(Get-Date) - INFO - Initialize connection")
    $null=$MsSqlConnection.Initialize()
  }
  Process{
    Try{
      Write-Verbose ("$(Get-Date) - INFO - New backup device item")
      $BackupDeviceItem=New-Object Microsoft.SQLServer.Management.Smo.BackupDeviceItem
      $BackupDeviceItem.Name=$backupFile
      $BackupDeviceItem.DeviceType="File"
      Write-Verbose ("$(Get-Date) - INFO - New restore device")
      $RestoreDevice=New-Object Microsoft.SQLServer.Management.Smo.Restore
      $RestoreDevice.Action="Database"
      $RestoreDevice.ReplaceDatabase=$true
      $RestoreDevice.NoRecovery=$false
      Write-Verbose ("$(Get-Date) - INFO - Add backup device item to restore device")
      $RestoreDevice.Devices.Add($BackupDeviceItem)
      Write-Verbose ("$(Get-Date) - INFO - Read backup header")
      $BackupHeader=$RestoreDevice.ReadBackupHeader($MsSqlConnection)
      Write-Verbose ("$(Get-Date) - INFO - Set databse name in restore device")
      $RestoreName=$BackupHeader.Rows[0].DatabaseName
      $RestoreDevice.Database=$RestoreName
      Write-Verbose ("$(Get-Date) - INFO - Read backup file list")
      $FileList=$RestoreDevice.ReadFileList($MsSqlConnection)
      Write-Verbose ("$(Get-Date) - INFO - Relocate mdf,ldf,ndf files")
      ForEach ($File in $FileList) {
        Write-Verbose ("$(Get-Date) - INFO - New relocate device")
        $RelocateFile=New-Object Microsoft.SqlServer.Management.Smo.RelocateFile
        Switch ($File.FileId) {
          1 {
            Write-Verbose ("$(Get-Date) - INFO - New physical path for mdf file")
            $NewPhysicalPath="{0}{1}.mdf" -f $MsSqlConnection.DefaultFile,$RestoreName
          }
          2 {
            Write-Verbose ("$(Get-Date) - INFO - New physical path for ldf file")
            $NewPhysicalPath="{0}{1}.ldf" -f $MsSqlConnection.DefaultFile,$RestoreName
          }
          Default {
            Continue
          }
        }
        Write-Verbose ("$(Get-Date) - INFO - Relocate files")
        $RelocateFile.LogicalFileName=$File.LogicalName
        $RelocateFile.PhysicalFileName=$NewPhysicalPath
        $null=$RestoreDevice.RelocateFiles.Add($RelocateFile)
      }
      Write-Verbose ("$(Get-Date) - INFO - Test if database already exists")
      If($MsSqlConnection.Databases[$RestoreName]){
        Write-Verbose ("$(Get-Date) - INFO - Kill all processes connected to database")
        $MsSqlConnection.KillAllProcesses($RestoreName)
        Write-Verbose ("$(Get-Date) - INFO - Set database offline")
        $MsSqlConnection.Databases[$RestoreName].SetOffline()
      }
      Else{
        Write-Verbose ("$(Get-Date) - INFO - Databse currently not present in SQL instance")
      }
      Write-Verbose ("$(Get-Date) - INFO - Restore device")
      $RestoreDevice.SQLRestore($MsSqlConnection)
      $MsSqlConnection.Databases.Refresh()
      Write-Verbose ("$(Get-Date) - INFO - Set database online")
      $MsSqlConnection.Databases[$RestoreName].SetOnline()
    }
    Catch{
      Write-Verbose ("$(Get-Date) - ERROR - {0}" -f $_.Exception.Message)
    }
    Finally{}
  }
  End{}
}

然后做:

Get-Help -Name Restore-MsSqlDatabase -Examples

以上是关于使用PowerShell和SMO库从.BAK文件创建新数据库的主要内容,如果未能解决你的问题,请参考以下文章

使用 smo 和 powershell 将数据库备份还原到新数据库时出错

sql 使用PowerShell和SMO为给定数据库中的MS SQL存储过程和视图创建drop + create脚本

从.bak文件还原sql数据库时出错

数据库还原失败

linux基础问题 创建目录 拷贝 重命名 设置权限

如何在 C# 中使用 SMO 使用 FILE STREAM 备份和恢复数据库