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

Posted

技术标签:

【中文标题】使用 smo 和 powershell 将数据库备份还原到新数据库时出错【英文标题】:Error restoring database backup to new database with smo and powershell 【发布时间】:2011-07-04 15:37:45 【问题描述】:

从另一台服务器上进行数据库备份,我正在尝试恢复到本地主机上的 sqlexpress。此恢复将通过 gui 进行,但我在使用 powershell 恢复它时遇到问题。我收到以下错误消息:

Exception calling "SqlRestore" with "1" argument(s): "Restore failed for Server
+ $smoRestore.SqlRestore <<<< ($server)
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException

错误信息指向这一行的第 23 个字符:

        $smoRestore.SqlRestore($server)

脚本:

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

Import-Module PSCX
Import-Module WebAdministration

function GetLatestItem()
    param([string]$RemotePath)
    $returnString = Get-ChildItem $RemotePath -force -filter "*.7z" | sort @expression=$_.LastWriteTime; Descending=$true | select Name -first 1
    return $returnString.Name


function DatabaseExists()
    param([Microsoft.SqlServer.Management.Smo.Server]$server,[string]$databaseName)
    foreach($database in $server.Databases)
        if($database.Name -eq $databaseName)
            $true
        
    
    $false


$LocalFile = "C:\backups\backupname.bak.7z"
$LocalFilePath = "C:\backups\"   

Expand-Archive $Localfile $LocalFilePath    

# Most of the restore information was found at http://www.sqlmusings.com/2009/06/01/how-to-restore-sql-server-databases-using-smo-and-powershell/
$backupFile = $LocalFilePath + [IO.Path]::GetFileNameWithoutExtension($LocalFile)
[Microsoft.SqlServer.Management.Smo.Server]$server = New-Object ("Microsoft.SqlServer.Management.Smo.Server") ".\SQLEXPRESS"
$backupDevice = New-Object ("Microsoft.SqlServer.Management.Smo.BackupDeviceItem") ($backupFile, "File")
$smoRestore = New-Object Microsoft.SqlServer.Management.Smo.Restore

$smoRestore.NoRecovery = $true;
$smoREstore.ReplaceDatabase = $true;
$smoRestore.Action = "Database"
$smoRestore.PercentCompleteNotification = 10;
$smoRestore.Devices.Add($backupDevice)

# Get the details from the backup device for the database name and output that
$smoRestoreDetails = $smoRestore.ReadBackupHeader($server)
$databaseName = $smoRestoreDetails.Rows[0]["DatabaseName"]

"Database Name from Backup Header : " + $databaseName
$smoRestore.Database = $databaseName    

if(DatabaseExists $server $databaseName -not)
    $smoRestoreFile = New-Object("Microsoft.SqlServer.Management.Smo.RelocateFile")
    $smoRestoreLog = New-Object("Microsoft.SqlServer.Management.Smo.RelocateFile")
    $smoRestoreFile.LogicalFileName = $smoRestoreDetails.Rows[0]["DatabaseName"]
    $smoRestoreFile.PhysicalFileName = $server.Information.MasterDBPath + "\" + $smoRestore.Database + "_Data.mdf"
    $smoRestoreLog.LogicalFileName = $smoRestoreDetails.Rows[0]["DatabaseName"] + "_Log"
    $smoRestoreLog.PhysicalFileName = $server.Information.MasterDBPath + "\" + $smoRestore.Database + "_Log.ldf"
    $smoRestore.RelocateFiles.Add($smoRestoreFile)
    $smoRestore.RelocateFiles.Add($smoRestoreLog)
 

$smoRestore.SqlRestore($server)
if($error.Count -eq 0)

else
    $Error[0].exception.message

【问题讨论】:

你的问题代码帮我解决了一个问题!谢谢:) 【参考方案1】:

我有一个与你的非常相似的脚本,但有一些值得注意的区别:

在致电SqlRestore 之前,我先致电$server.KillAllProcesses($databaseName)。 我有$smoRestore.NoRecovery = $false,而不是$true 我有$smoRestore.FileNumber = 1,而你根本没有。我认为这对应于从 GUI 中的备份集中检查文件。

我也有类似的代码来设置逻辑/物理文件名,但我没有使用$server.Information,而是从注册表中提取信息(不确定哪个“更好”)。另一个区别是我使用$smoRestore.ReadFileList 而不是$smoRestore.ReadBackupHeader

您也可以尝试在路径上使用一些 Write-Host 语句以确保它们看起来正确,如果您还没有这样做的话。

希望其中一个项目符号调整可以解决您的问题。如果您想从我的脚本中获得更多信息,请告诉我。

【讨论】:

对于任何未来的读者来说,添加“$smoRestore.FileNumber = 1”是为我做到的诀窍。 您也可以尝试深入挖掘异常。尝试使用:$Error[0].exception.GetBaseException().Message【参考方案2】:

我和一位同事都遇到了这个问题,经过一些故障排除后,我们发现关闭 SQL Server Management Studio 可以解决问题。

希望其他人可以跳过我们所做的所有故障排除,这个简单的解决方案可以为他们节省几个小时。

【讨论】:

以上是关于使用 smo 和 powershell 将数据库备份还原到新数据库时出错的主要内容,如果未能解决你的问题,请参考以下文章

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

将 SMO 数据类型转换为 SqlDataTypes

使用 SMO 复制数据库和数据

Microsoft.SqlServer.Management.Smo - 如何将列数据类型转换为 sql 表示

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

将 LinqPad 与 SMO 一起使用