当我们从生产中复制数据库时,我们会对数据库进行备份,将其压缩并复制备份。然后我们必须使用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'
正如您所看到的,这似乎效率低下,因为您必须手动将逻辑文件名输入到下一个查询中。
您可以在下面找到我对此问题的解决方案。
答案 0 :(得分:4)
这是一个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
答案 1 :(得分:3)
使用各种资源我提出了以下存储过程,可以让您将此恢复简化为一步。我希望它证明对别人有用,就像对自己一样。
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
我确信有关此查询的一些内容可以改进,但是我已经浪费了足够的时间来尝试解决此问题。无论我喜欢听到一些反馈。我希望其他人觉得这很有用!