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

Sql server Microsoft SQL Server,使用一个命令还原数据库备份,sql-server,sql-server-2005,tsql,Sql Server,Sql Server 2005,Tsql,当我们从生产环境中复制数据库时,我们对数据库进行备份、压缩并复制备份。然后,我们必须使用SQLServerGUI进行恢复,这涉及到在多个菜单和窗口中导航。据我所知,SQL Server的内置存储过程无法做到这一点,因为您可能不知道数据库的逻辑文件名(还原时需要该文件名)。因此,通过查询执行此操作包括以下内容: RESTORE FILELISTONLY FROM DISK = 'C:\backup_of_production_database.bak' GO 上面提供了备份文件中的逻辑文件名,然

当我们从生产环境中复制数据库时,我们对数据库进行备份、压缩并复制备份。然后,我们必须使用SQLServerGUI进行恢复,这涉及到在多个菜单和窗口中导航。据我所知,SQL Server的内置存储过程无法做到这一点,因为您可能不知道数据库的
逻辑文件名
(还原时需要该文件名)。因此,通过查询执行此操作包括以下内容:

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'
如您所见,这似乎效率低下,因为您必须在下一个查询中手动输入逻辑文件名

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

解决方案: 使用各种资源,我提出了以下存储过程,可以将此恢复简化为一个步骤。我希望它能像对我一样对别人有用

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

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

下面是一个SQL脚本,它将在不需要交互的情况下恢复数据库。 只需输入您的“源数据库”和“目标数据库”-脚本将完成其余工作:)


请把这个分成问题和答案。否则谢谢!如果LogicalName与PhysicalName不同,这将不起作用。如果有多个数据库具有相同的“名称”但不同的“物理名称”,这也会有问题。SELECTFROM“master.sys.master_文件”中的where子句需要更具体。除此之外,还有一个非常有用的脚本。
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