代码之家  ›  专栏  ›  技术社区  ›  configurator

Microsoft SQL Server,用一个命令还原数据库的备份

  •  5
  • configurator  · 技术社区  · 6 年前

    当我们从生产环境中复制数据库时,我们会备份数据库,将其压缩并复制备份。然后,我们必须使用SQL Server GUI进行恢复,这涉及到通过几个菜单和窗口进行导航。据我所知,您不能使用SQL Server的内置存储过程执行此操作,因为您可能不知道 logical filename 数据库(需要还原)。因此,通过查询执行此操作包括以下内容:

    RESTORE FILELISTONLY
    FROM DISK = 'C:\backup_of_production_database.bak'
    GO
    

    上面提供了备份文件中的逻辑文件名,然后您必须在下一个查询中使用这些逻辑名称…

    RESTORE DATABASE NewDevelopmentDatabase
    FROM DISK = 'C:\backup_of_production_database.bak'
    WITH MOVE 'YourMDFLogicalName' TO 'C:\mssql\data\DataYourMDFFile.mdf',
    MOVE 'YourLDFLogicalName' TO 'C:\mssql\data\DataYourLDFFile.mdf'
    

    如您所见,这似乎效率低下,因为您必须在下一个查询中手动输入逻辑文件名。

    你可以在下面找到这个问题的解决方案。

    2 回复  |  直到 12 年前
        1
  •  4
  •   MWD    12 年前

    下面是一个SQL脚本,它将在不需要交互的情况下还原数据库。 只需输入“源数据库”和“目标数据库”-脚本将执行其余操作:)

    SET NOCOUNT ON;
    
    DECLARE 
        @MySourceDatabase NVarchar(1000),
        @MyDestinationDatabase NVarchar(100),
        @DeviceFrom NVarchar(1000),
        @DeviceTo NVarchar(1000),
        @LogicalName NVarchar(1000),
        @PhysicalName NVarchar(1000),
        @SQL NVarchar(MAX),
        @RowsToProcess integer,
        @CurrentRow integer,
        @Comma NVarchar(25);
    
    --SOURCE DATABASE (DATABASE TO RESTORE)
    SET @MySourceDatabase = 'D:\Backups\backup_db.bak';
    
    --DESTINATION DATABASE (DATABASE TO RESTORE TO)
    SET @MyDestinationDatabase = 'mydatabase_db';
    
    SELECT @DeviceFrom = SUBSTRING(physical_name, 1,
    CHARINDEX(@MyDestinationDatabase + '.mdf',
    physical_name) - 1) 
    FROM master.sys.master_files
    WHERE name = @MyDestinationDatabase AND FILE_ID = 1;
    
    SET @SQL = 'RESTORE DATABASE ' + @MyDestinationDatabase + ' FROM DISK = ''' + @MySourceDatabase + ''' WITH ';
    SET @CurrentRow = 0;
    SET @Comma = ',';
    
    DECLARE @FileList TABLE (
        RowID int not null primary key identity(1,1)
        ,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 BIGINT 
        ,FilegroupId BIGINT 
        ,LogGroupGUID uniqueidentifier 
        ,DifferentialBaseLSN numeric(25) 
        ,DifferentialBaseGUID uniqueidentifier 
        ,IsReadOnly BIGINT 
        ,IsPresent BIGINT
        ,TDEThumbprint VARBINARY(32) -- Remove this line for SQL Server 2005
        );
    
    INSERT INTO @FileList
    EXEC('RESTORE FILELISTONLY FROM DISK = ''' + @MySourceDatabase + '''')
    SET @RowsToProcess = @@RowCount;
    
    WHILE @CurrentRow < @RowsToProcess
    BEGIN
        SET @CurrentRow= @CurrentRow + 1;
        BEGIN
        IF @CurrentRow = @RowsToProcess
            SET @Comma = ',REPLACE';
        END
        SELECT @LogicalName = LogicalName,@PhysicalName = PhysicalName FROM @FileList WHERE RowID=@CurrentRow;
        SET @PhysicalName = Replace(@PhysicalName,@LogicalName,@MyDestinationDatabase);
        SET @SQL = @SQL + 'MOVE ''' + @LogicalName + ''' TO ''' + @PhysicalName + '''' + @Comma + '';
    END
    
    --PREVIEW THE GENERATED QUERY
    SELECT @SQL;
    
    --EXECUTE THE GENERATED QUERY
    --EXEC(@SQL);
    

    它将自动生成如下查询:

    RESTORE DATABASE mydatabase_db 
    FROM DISK = 'D:\Backups\backup_db.bak' 
    WITH 
    MOVE 'backup_db' 
    TO 'C:\Program Files\Microsoft SQL Server\MSSQL10_50.SQLEXPRESS\MSSQL\DATA\mydatabase_db.mdf',
    MOVE 'backup_db_log' 
    TO 'C:\Program Files\Microsoft SQL Server\MSSQL10_50.SQLEXPRESS\MSSQL\DATA\mydatabase_db.LDF',
    REPLACE
    
        2
  •  3
  •   danieljimenez    16 年前

    解决方案:

    使用各种资源,我想到了下面的存储过程,它允许您将这个恢复过程简化为一个步骤。我希望它能像对我自己一样对别人有用。

    ALTER PROCEDURE [dbo].[sp_makedev] 
        @backupfile sysname,
        @newdatabase sysname
    AS
    BEGIN
    
    DECLARE @fname VARCHAR(200) 
    DECLARE @dirfile VARCHAR(300) 
    DECLARE @LogicalName NVARCHAR(128) 
    DECLARE @PhysicalName NVARCHAR(260) 
    DECLARE @type CHAR(1) 
    DECLARE @sql NVARCHAR(1000) 
    DECLARE @mdfFilePath  varchar(1000)
    DECLARE @ldfFilePath varchar(1000)
    
    CREATE TABLE #dbfiles( 
     LogicalName NVARCHAR(128) 
    ,PhysicalName NVARCHAR(260) 
    ,Type CHAR(1) 
    ,FileGroupName NVARCHAR(128) 
    ,Size numeric(20,0) 
    ,MaxSize numeric(20,0) 
    ,FileId INT 
    ,CreateLSN numeric(25,0) 
    ,DropLSN numeric(25,0) 
    ,UniqueId uniqueidentifier 
    ,ReadOnlyLSN numeric(25,0) 
    ,ReadWriteLSN numeric(25,0) 
    ,BackupSizeInBytes INT 
    ,SourceBlockSize INT 
    ,FilegroupId INT 
    ,LogGroupGUID uniqueidentifier 
    ,DifferentialBaseLSN numeric(25) 
    ,DifferentialBaseGUID uniqueidentifier 
    ,IsReadOnly INT 
    ,IsPresent INT 
    )
    
    set @mdfFilePath = ''c:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\data''
    set @ldfFilePath = ''c:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\data''
    set @sql = ''RESTORE DATABASE '' + @newdatabase + '' FROM DISK = '''''' + @backupfile + '''''' WITH MOVE '' 
    
    DECLARE dbfiles CURSOR FOR 
    SELECT LogicalName, PhysicalName, [type] FROM #dbfiles 
    
    INSERT #dbfiles 
    EXEC(''RESTORE FILELISTONLY FROM DISK = '''''' + @backupfile + '''''''') 
    
    OPEN dbfiles 
    FETCH NEXT FROM dbfiles INTO @LogicalName, @PhysicalName, @type 
    WHILE @@FETCH_STATUS = 0 
    BEGIN 
    IF @type = ''D'' 
        SET @sql = @sql + '''''''' + @LogicalName + '''''' TO '''''' + @mdfFilePath + ''\'' + @newdatabase  + ''.mdf'''', MOVE '' 
    ELSE IF @type = ''L'' 
        SET @sql = @sql + '''''''' + @LogicalName + '''''' TO '''''' +  @ldfFilePath + ''\'' + @newdatabase  + ''.ldf'''''' 
    
    FETCH NEXT FROM dbfiles INTO @LogicalName, @PhysicalName, @type 
    END 
    
    CLOSE dbfiles
    DEALLOCATE dbfiles
    EXEC(@SQL)
    END
    

    我相信关于这个查询的一些东西可以改进,但是我已经浪费了足够的时间来尝试这个解决方案。不管怎样,我很想听到一些反馈。我希望其他人觉得这有用!