如何在不知道目标路径或文件名的情况下还原SQL Server数据库备份?

时间:2012-02-22 02:57:47

标签: sql-server sql-server-2008 tsql database-restore

我需要以编程方式(T-SQL)还原SQL Server 2008中的数据库备份。此备份来自不同的服务器,原始数据库名称也可能不同。 (实际上,我正在将数据库从某个服务器复制到另一台服务器上的新数据库。)

显然,我必须使用RESTORE DATABASE ... WITH MOVE,但是我需要知道应该将文件恢复到哪里以及如何命名它们。尽管搜索,我还没有找到似乎是最基本的任务:只使用默认路径和文件名,即执行SQL Server在发出CREATE DATABASE时所做的一切 - 您不必指定该命令的路径,为什么RESTORE需要它?

我是否忽略了一些简单的解决方案,或者我是否真的必须列出文件,以某种方式从SQL Server配置中找到数据库目录,并使用该信息构建RESTORE命令?感谢。

(与PostgreSQL相比,使用pg_restore时,你指定一个已经创建的目标数据库;当你创建它时,你有选择 - 不是必须的 - 指定一个非默认的表空间,但如果你没有' t,你只是不关心文件的物理存储位置。)

7 个答案:

答案 0 :(得分:9)

未来的Google员工;从 SQL Server 2012 开始 ,您可以使用:

SELECT ServerProperty(N'InstanceDefaultDataPath') AS default_file
     , ServerProperty(N'InstanceDefaultLogPath') AS default_log
;

这将读取服务器属性>下显示的文件夹路径。数据库设置>数据库默认位置

Server Properties > Database Settings

答案 1 :(得分:5)

CREATE DATABASE命令将使用默认路径创建数据库,因此您可以创建数据库,然后使用替换语法(sqlcmd模式)对其进行恢复:

:setvar DatabaseName MyDatabase
declare @fileName varchar(255)
set @fileName = 'c:\backup\mybackup.bak'

if db_id('$(DatabaseName)') is null
            CREATE DATABASE [$(DatabaseName)]

RESTORE DATABASE [$(DatabaseName)]
FROM DISK = @fileName
WITH REPLACE

答案 2 :(得分:4)

我刚才写了一个函数,它为你做了这个。它支持所有版本的SQL Server,包括具有默认实例和命名实例的安装。 See here for the code and an example

要进行恢复,您将调用如下所示的函数。

declare @sql nvarchar(2000), 
        @data varchar(260), 
        @log varchar(260); 

select @data = dbo.fn_get_default_path(0),
       @log = dbo.fn_get_default_path(1)

SELECT @sql= 'RESTORE DATABASE DefaultLocationDB 
FROM  DISK = N''c:\backups\DemoDB.bak'' WITH  FILE = 1,  
MOVE N''demo_data_device'' TO N''' + @data + '\DemoDb.mdf'',  
MOVE N''demo_log_device'' TO N''' +  @log + '\DemoDb.ldf'',  
NOUNLOAD, REPLACE'

exec (@sql)

答案 3 :(得分:2)

您必须阅读注册表,例如

DECLARE @Result NVARCHAR(4000) 
EXECUTE [master].[dbo].xp_instance_regread 
N'HKEY_LOCAL_MACHINE', 
N'Software\Microsoft\MSSQLServer\MSSQLServer',N'BackupDirectory', 
@Result OUTPUT,  
'NO_OUTPUT' 
SELECT @Result

答案 4 :(得分:2)

我必须自己这样做,最后我结合了几个答案来创建一个恢复数据库(任何数据库)并重新映射文​​件的脚本。您只需知道备份文件的路径和新的数据库名称。不幸的是,这个问题似乎没有任何简洁的解决方案。

DECLARE @Source nvarchar(max) = 'C:\backup.bak'
DECLARE @RestoreDestination nvarchar(max) = 'NewDatabaseName'

--https://stackoverflow.com/a/27893494/5734516
--https://stackoverflow.com/a/4018782/5734516
DECLARE @fileListTable TABLE (
    [LogicalName]           NVARCHAR(128),
    [PhysicalName]          NVARCHAR(260),
    [Type]                  CHAR(1),
    [FileGroupName]         NVARCHAR(128),
    [Size]                  NUMERIC(20,0),
    [MaxSize]               NUMERIC(20,0),
    [FileID]                BIGINT,
    [CreateLSN]             NUMERIC(25,0),
    [DropLSN]               NUMERIC(25,0),
    [UniqueID]              UNIQUEIDENTIFIER,
    [ReadOnlyLSN]           NUMERIC(25,0),
    [ReadWriteLSN]          NUMERIC(25,0),
    [BackupSizeInBytes]     BIGINT,
    [SourceBlockSize]       INT,
    [FileGroupID]           INT,
    [LogGroupGUID]          UNIQUEIDENTIFIER,
    [DifferentialBaseLSN]   NUMERIC(25,0),
    [DifferentialBaseGUID]  UNIQUEIDENTIFIER,
    [IsReadOnly]            BIT,
    [IsPresent]             BIT,
    [TDEThumbprint]         VARBINARY(32) -- remove this column if using SQL 2005
)

DECLARE @QueryCommand nvarchar(max) =
 'RESTORE FILELISTONLY FROM DISK = N''' + REPLACE(@Source, '''', '''''') + ''' WITH NOUNLOAD'

INSERT INTO @fileListTable 
EXEC(@QueryCommand)


--https://stackoverflow.com/a/2014673/5734516
DECLARE @filepath NVARCHAR(260)
EXEC master.dbo.xp_instance_regread 
        N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer', 
        N'DefaultData', 
        @filepath output, 'no_output'


DECLARE @Command nvarchar(max) 
SET @Command = 'RESTORE DATABASE ' + QUOTENAME(@RestoreDestination)  + ' '
                + ' FROM DISK=N''' + REPLACE(@Source, '''', '''''') + ''' '
                + 'WITH FILE=1 '
SELECT 
    @Command = @Command + ',MOVE N''' + REPLACE(LogicalName, '''', '''''') + '''' 
    + ' TO N'''  
        + REPLACE(@filepath + '\' + @RestoreDestination + case when FileID = 1 then '.mdf' when Type = 'L' then '_' + CAST(FileID as varchar(max)) + '.ldf' else '_' + CAST(FileID as varchar(max)) + '.ndf' end, '''', '''''')
    + '''' 
FROM @fileListTable 

SELECT @Command
EXEC(@Command)

注意:我知道这是一个老帖子,但它可能对前进的人有用。

答案 5 :(得分:1)

如前所述,CREATE DATABASE在默认位置创建文件。 然后,您可以找到这些文件的路径,并使用RESTORE部分

中的文件
-- Database will be created in default location
CREATE DATABASE [MyRestoredDatabase] 

DECLARE @mdfFile VARCHAR(MAX)
DECLARE @ldfFile VARCHAR(MAX)

SELECT @mdfFile = physical_name
FROM sys.master_files
WHERE database_id = DB_ID('MyRestoredDatabase')
AND file_id = 1

SELECT @ldfFile = physical_name
FROM sys.master_files
WHERE database_id = DB_ID('MyRestoredDatabase')
AND file_id = 2

-- Overwrite known files of the new database from restore 
RESTORE DATABASE [MyRestoredDatabase] 
FROM DISK='C:\Path\To\OriginalDatabase.bak'
WITH REPLACE,
    MOVE 'OriginalDatabase' TO @mdfFile,
    MOVE 'OriginalDatabase_Log' TO @ldfFile

如果需要查找逻辑名称,请使用以下SQL

RESTORE FILELISTONLY
FROM DISK='C:\Path\To\MyRestoredDatabase.bak'

可以找到全自动脚本here

答案 6 :(得分:0)

如果您的意思是使用Management Studio的“新建数据库”选项,则会默认使用某些值。但是CREATE DATABASE的T-SQL仍然需要路径。您可以通过转到管理工作室,选择“新建数据库”,输入新名称,然后单击“脚本”按钮来查看。此按钮将为您提供SQL Server将运行的T-SQL。此过程实际上并未运行,因此您可以取消“新建数据库”向导。

还原时还有一个类似的按钮。因此,如果您已经拥有所有信息并且只需要T-SQL,请通过管理工作室进行还原,但不要单击“确定”以运行该过程,而是单击“脚本”按钮,该按钮将生成带有默认值的T-SQL值。

希望这有帮助。