SQL 使用新文件名的服务器还原数据库

SQL Server Restore Database with new file names

是否可以从备份恢复 SQL 服务器数据库,同时使用新名称创建 *.mdf*.ldf 文件?

假设我知道每个备份只有两个文件(一个 mdf 和一个 ldf),但我不知道这些文件的确切名称,不幸的是我不能' t 从数据库名称派生它们。

所有这一切的目的是创建批处理文件,该文件将从一组备份文件中恢复数据库。同时我必须解决文件名冲突的问题。

目前我有这个命令,它不适用于每个备份,因为一些数据库文件的命名与变量 %DATABASENAME% 不同:

...
RESTORE DATABASE [%NewDB%] 
FROM DISK = N'%BACKUPFILENAME%' 
WITH RECOVERY,  
MOVE N'%DATABASENAME%' TO N'C:\%NewDB%.mdf',  
MOVE N'%DATABASENAME%_Log' TO N'C:\%NewDB%_Log.ldf'
...

可以使用RESTORE FILELISTONLY获取备份中数据文件的详细信息。

您可以将此信息放入 table 中,您可以通过将其插入临时 table 或 table 变量来构建还原语句。要将其集成到您现有的代码中:

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)
)

--This schema works from SQL 2008 to SQL 2014. 
--SQL 2005 didn't have the TDEThumbprint column, but is otherwise the same.

INSERT INTO @fileListTable EXEC('restore filelistonly 
FROM DISK = N''%BACKUPFILENAME%''')

DECLARE @datafile NVARCHAR(128), @logfile NVARCHAR(128)

SELECT @datafile = LogicalName FROM @fileListTable WHERE Type = 'D'

SELECT @logfile = LogicalName FROM @fileListTable WHERE Type = 'L'

RESTORE DATABASE [%NewDB%] 
FROM DISK = N'%BACKUPFILENAME%' 
WITH RECOVERY,  
MOVE @datafile TO N'C:\%NewDB%.mdf',  
MOVE @logfile TO N'C:\%NewDB%_Log.ldf'

在data/log个文件的场景下,代码需要相应地更复杂。

解决文件名冲突可能性的一种方法是将时间戳、GUID 或其他合理的唯一标识符附加到新文件名。

基于上述回答,我创建了一个存储过程,我从批处理文件中执行:

Create Procedure restoreDB
    @filepath nvarchar(700),
    @dbname nvarchar(200)

    as

    declare @dbfile nvarchar(300)
    declare @dblogfile nvarchar(300)

    declare @newdbfile nvarchar(300)
    declare @newdblogfile nvarchar(300)

    select @dbname = ltrim(@dbname)
    set @newdbfile = 'c:\' + @dbname + '.mdf'
    set @newdblogfile = 'c:\' + @dbname + '.ldf'


    DECLARE @Filenames 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,
        IsReadOnl            bit,
        IsPresent            bit,
        TDEThumbprint        varbinary(32)
    )

    INSERT INTO @Filenames
    EXEC('restore filelistonly from disk=''' + @filepath + '''');

    select @dbfile = (select top 1 LogicalName from @Filenames where [Type] = 'd');
    select @dblogfile = (select top 1 LogicalName from @Filenames where [Type]='l');

    RESTORE DATABASE @dbname FROM  DISK = @filepath WITH  RECOVERY,  MOVE @dbfile TO @newdbfile,  MOVE @dblogfile TO @newdblogfile;