使用PowerShell和SMO库

时间:2017-12-01 14:27:00

标签: powershell sql-server-2012 smo

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

这是我的剧本:

TRY
{
    [System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.SMO') | out-null 
    [System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.SmoExtended') | out-null
    $servername = "MyServer\MyServerInstance"
    $datapath= "E:\SQLData\MyNewDataBase"
    $logpath= "E:\SQLLogs\MyNewDataBase"
    $path= "\\MyServer\BKPFolder\"
    $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文件。

我错过了什么?

感谢。

2 个答案:

答案 0 :(得分:2)

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

[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:\SQLData\MyNewDataBase_DATA.mdf")
    $RelocateLog = New-Object Microsoft.SqlServer.Management.Smo.RelocateFile("OldDataBase_Log", "E:\SQLLogs\MyNewDataBase_LOG.ldf")

    #Executa a restauração
    Restore-SqlDatabase -ServerInstance "MyServer\MyServerInstance" -Database "MyNewDataBase" -BackupFile "\\BackupFolder\OldDataBase.bak" -RelocateFile @($RelocateData,$RelocateLog) -NoRecovery
    Restore-SqlDatabase -ServerInstance "MyServer\MyServerInstance" -Database "MyNewDataBase" -BackupFile "\\BackupFolder\OldDataBase.trn" -RestoreAction Log -NoRecovery 

答案 1 :(得分:1)

希望这就是你所需要的:

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:\backups\aateam_20491005.bak' -Verbose
.Example
  Restore-MsSqlDatabase -BackupFile 'D:\backups\aateam_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