在不知道逻辑文件名的情况下恢复 SQL 服务器数据库
Restore SQL Server database without knowing the Logical File Names
我有一个用于恢复数据库的批处理文件。这些 .bak
文件是由我们部门以外的其他人创建的,数据库名称是不可预测的,因为它们通常是根据我们不同的客户命名的。
SET servername=XXXXXX
SET mssqldir=C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL
SET datapath=%mssqldir%\DATA
SET dbfile=%~1
SqlCmd -E -S %servername% -Q "RESTORE DATABASE [MyDatabase] FROM DISK = N'%dbfile%' WITH FILE = 1, MOVE 'Customer' TO N'%datapath%\Customer.mdf', MOVE 'Customer_log' TO '%datapath%\Customer.ldf', NOUNLOAD, STATS = 10"
如上所述,上述命令的问题在于 Customer
并不总是 Customer
。
所以当我 运行 它时,我得到类似的东西:
Msg 3234, Level 16, State 2, Server XXXXXX, Line 1
Logical file 'Customer' is not part of database 'MyDatabase'. Use RESTORE FILELISTONLY to list the logical file names.
Msg 3013, Level 16, State 1, Server XXXXXX, Line 1
RESTORE DATABASE is terminating abnormally.
如果我尝试在没有 MOVE 子句的情况下进行还原,还原会尝试将文件 "back" 放在它们最初来自的位置——就像包含其他人的主目录的路径:
Msg 5133, Level 16, State 1, Server XXXXXX, Line 1
Directory lookup for the file "C:\TEMP\Not.Me\WidgetsRUs.mdf" failed with the operating system error 2(The system cannot find the file specified.).
我希望有一种神奇的方式可以基本上说:MOVE '*.*' TO '"%datapath%'
有什么想法吗?
按照建议,使用 RESTORE FILELISTONLY 获取数据库和日志名称
@echo off
SetLocal EnableDelayedExpansion EnableExtensions
set "servername=XXXXXX"
set "mssqldir=C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL"
set "datapath=%mssqldir%\DATA"
set "dbfile=%~1"
set "command=" & set "restore="
set "database=" & set "databaselog="
set "command=%command%DECLARE @Table TABLE (LogicalName varchar(128),[PhysicalName] varchar(128),[Type] varchar,[FileGroupName] varchar(128),"
set "command=%command%[Size] varchar(128),[MaxSize] varchar(128),[FileId] varchar(128),[CreateLSN] varchar(128),[DropLSN] varchar(128),"
set "command=%command%[UniqueId] varchar(128),[ReadOnlyLSN] varchar(128),[ReadWriteLSN] varchar(128),[BackupSizeInBytes] varchar(128),"
set "command=%command%[SourceBlockSize] varchar(128),[FileGroupId] varchar(128),[LogGroupGUID] varchar(128),[DifferentialBaseLSN] varchar(128),"
set "command=%command%[DifferentialBaseGUID] varchar(128),[IsReadOnly] varchar(128),[IsPresent] varchar(128),[TDEThumbprint] varchar(128));"
set "command=%command%DECLARE @LogicalNameData varchar(128),@LogicalNameLog varchar(128);"
set "command=%command%INSERT INTO @table EXEC('RESTORE FILELISTONLY FROM DISK='''+'%dbfile%'+''' ');"
set "command=%command%SET @LogicalNameData=(SELECT LogicalName FROM @Table WHERE Type='D');"
set "command=%command%SET @LogicalNameLog=(SELECT LogicalName FROM @Table WHERE Type='L');"
set "command=%command%SELECT @LogicalNameData,@LogicalNameLog;"
set "restore=%restore%RESTORE DATABASE [MyDatabase] FROM DISK = N'%dbfile%' WITH FILE = 1, "
set "restore=%restore%MOVE '%database%' TO N'%datapath%\Customer.mdf', "
set "restore=%restore%MOVE '%databaselog%' TO '%datapath%\Customer.ldf', "
set "restore=%restore%NOUNLOAD, STATS = 10"
for /f "skip=2 usebackq tokens=1,2* delims= " %%a in (`sqlcmd -h-1 -b -E -S %servername% -Q "%command%"`) do if not defined database set "database=%%a" & set "databaselog=%%b"
echo %database%
echo %databaselog%
if not exist "%datapath%" md "%datapath%">nul
sqlcmd -E -S %servername% -Q "%restore%"
EndLocal
exit/B 1
基于@Elzooilogico 的回答。我想我只是包括我的最终版本,以防它为其他人增加一些清晰度。
@ECHO OFF
SET servername=XXXXXXX
SET mssqldir=C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL
SET datapath=%mssqldir%\DATA
SET dbfile=%mssqldir%\Backup\default.bak
SET isDefault=true
IF NOT "%~1"=="" (
SET dbfile=%~1
SET isDefault=false
)
ECHO Target file: %dbfile%
ECHO.
ECHO Closing connections ...
SqlCmd -E -S %servername% -Q "ALTER DATABASE MyDatabase SET SINGLE_USER WITH ROLLBACK IMMEDIATE"
ECHO.
ECHO Removing old database ...
SqlCmd -E -S %servername% -Q "DROP DATABASE MyDatabase"
SET command=
SET command=%command%DECLARE @FileListTable TABLE (
SET command=%command% [LogicalName] NVARCHAR(128),
SET command=%command% [PhysicalName] NVARCHAR(260),
SET command=%command% [Type] CHAR(1),
SET command=%command% [FileGroupName] NVARCHAR(128),
SET command=%command% [Size] NUMERIC(20,0),
SET command=%command% [MaxSize] NUMERIC(20,0),
SET command=%command% [FileId] BIGINT,
SET command=%command% [CreateLSN] NUMERIC(25,0),
SET command=%command% [DropLSN] NUMERIC(25,0),
SET command=%command% [UniqueId] UNIQUEIDENTIFIER,
SET command=%command% [ReadOnlyLSN] NUMERIC(25,0),
SET command=%command% [ReadWriteLSN] NUMERIC(25,0),
SET command=%command% [BackupSizeInBytes] BIGINT,
SET command=%command% [SourceBlockSize] INT,
SET command=%command% [FileGroupID] INT,
SET command=%command% [LogGroupGUID] UNIQUEIDENTIFIER,
SET command=%command% [DifferentialBaseLSN] NUMERIC(25,0),
SET command=%command% [DifferentialBaseGUID] UNIQUEIDENTIFIER,
SET command=%command% [IsReadOnly] BIT,
SET command=%command% [IsPresent] BIT,
SET command=%command% [TDEThumbprint] VARBINARY(32),
SET command=%command% [SnapshotUrl] NVARCHAR(360)
SET command=%command%);
SET command=%command%INSERT INTO @FileListTable EXEC('RESTORE FILELISTONLY FROM DISK = ''%dbfile%''');
SET command=%command%SELECT [LogicalName], [Type] FROM @fileListTable;
SET command=%command%DECLARE @LogicalNameData varchar(128), @LogicalNameLog varchar(128);
SET command=%command%SET @LogicalNameData=(SELECT LogicalName FROM @FileListTable WHERE Type='D');
SET command=%command%SET @LogicalNameLog=(SELECT LogicalName FROM @FileListTable WHERE Type='L');
SET command=%command%RESTORE DATABASE [MyDatabase] FROM DISK = N'%dbfile%' WITH FILE = 1,
SET command=%command% MOVE @LogicalNameData TO N'%datapath%\MyDatabase.mdf',
SET command=%command% MOVE @LogicalNameLog TO N'%datapath%\MyDatabase.ldf',
SET command=%command% NOUNLOAD, STATS = 10;
ECHO.
ECHO Resotring database from file ...
SqlCmd -E -S %servername% -Q "%command%"
ECHO.
ECHO Changing Owner ...
SqlCmd -E -S %servername% -d "MyDatabase" -Q "EXEC sp_changedbowner 'sa'"
ECHO.
ECHO.
IF "%isDefault%"=="false" (
PAUSE
REM timeout /t 3
)
我有一个用于恢复数据库的批处理文件。这些 .bak
文件是由我们部门以外的其他人创建的,数据库名称是不可预测的,因为它们通常是根据我们不同的客户命名的。
SET servername=XXXXXX
SET mssqldir=C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL
SET datapath=%mssqldir%\DATA
SET dbfile=%~1
SqlCmd -E -S %servername% -Q "RESTORE DATABASE [MyDatabase] FROM DISK = N'%dbfile%' WITH FILE = 1, MOVE 'Customer' TO N'%datapath%\Customer.mdf', MOVE 'Customer_log' TO '%datapath%\Customer.ldf', NOUNLOAD, STATS = 10"
如上所述,上述命令的问题在于 Customer
并不总是 Customer
。
所以当我 运行 它时,我得到类似的东西:
Msg 3234, Level 16, State 2, Server XXXXXX, Line 1
Logical file 'Customer' is not part of database 'MyDatabase'. Use RESTORE FILELISTONLY to list the logical file names.Msg 3013, Level 16, State 1, Server XXXXXX, Line 1
RESTORE DATABASE is terminating abnormally.
如果我尝试在没有 MOVE 子句的情况下进行还原,还原会尝试将文件 "back" 放在它们最初来自的位置——就像包含其他人的主目录的路径:
Msg 5133, Level 16, State 1, Server XXXXXX, Line 1
Directory lookup for the file "C:\TEMP\Not.Me\WidgetsRUs.mdf" failed with the operating system error 2(The system cannot find the file specified.).
我希望有一种神奇的方式可以基本上说:MOVE '*.*' TO '"%datapath%'
有什么想法吗?
按照建议,使用 RESTORE FILELISTONLY 获取数据库和日志名称
@echo off
SetLocal EnableDelayedExpansion EnableExtensions
set "servername=XXXXXX"
set "mssqldir=C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL"
set "datapath=%mssqldir%\DATA"
set "dbfile=%~1"
set "command=" & set "restore="
set "database=" & set "databaselog="
set "command=%command%DECLARE @Table TABLE (LogicalName varchar(128),[PhysicalName] varchar(128),[Type] varchar,[FileGroupName] varchar(128),"
set "command=%command%[Size] varchar(128),[MaxSize] varchar(128),[FileId] varchar(128),[CreateLSN] varchar(128),[DropLSN] varchar(128),"
set "command=%command%[UniqueId] varchar(128),[ReadOnlyLSN] varchar(128),[ReadWriteLSN] varchar(128),[BackupSizeInBytes] varchar(128),"
set "command=%command%[SourceBlockSize] varchar(128),[FileGroupId] varchar(128),[LogGroupGUID] varchar(128),[DifferentialBaseLSN] varchar(128),"
set "command=%command%[DifferentialBaseGUID] varchar(128),[IsReadOnly] varchar(128),[IsPresent] varchar(128),[TDEThumbprint] varchar(128));"
set "command=%command%DECLARE @LogicalNameData varchar(128),@LogicalNameLog varchar(128);"
set "command=%command%INSERT INTO @table EXEC('RESTORE FILELISTONLY FROM DISK='''+'%dbfile%'+''' ');"
set "command=%command%SET @LogicalNameData=(SELECT LogicalName FROM @Table WHERE Type='D');"
set "command=%command%SET @LogicalNameLog=(SELECT LogicalName FROM @Table WHERE Type='L');"
set "command=%command%SELECT @LogicalNameData,@LogicalNameLog;"
set "restore=%restore%RESTORE DATABASE [MyDatabase] FROM DISK = N'%dbfile%' WITH FILE = 1, "
set "restore=%restore%MOVE '%database%' TO N'%datapath%\Customer.mdf', "
set "restore=%restore%MOVE '%databaselog%' TO '%datapath%\Customer.ldf', "
set "restore=%restore%NOUNLOAD, STATS = 10"
for /f "skip=2 usebackq tokens=1,2* delims= " %%a in (`sqlcmd -h-1 -b -E -S %servername% -Q "%command%"`) do if not defined database set "database=%%a" & set "databaselog=%%b"
echo %database%
echo %databaselog%
if not exist "%datapath%" md "%datapath%">nul
sqlcmd -E -S %servername% -Q "%restore%"
EndLocal
exit/B 1
基于@Elzooilogico 的回答。我想我只是包括我的最终版本,以防它为其他人增加一些清晰度。
@ECHO OFF
SET servername=XXXXXXX
SET mssqldir=C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL
SET datapath=%mssqldir%\DATA
SET dbfile=%mssqldir%\Backup\default.bak
SET isDefault=true
IF NOT "%~1"=="" (
SET dbfile=%~1
SET isDefault=false
)
ECHO Target file: %dbfile%
ECHO.
ECHO Closing connections ...
SqlCmd -E -S %servername% -Q "ALTER DATABASE MyDatabase SET SINGLE_USER WITH ROLLBACK IMMEDIATE"
ECHO.
ECHO Removing old database ...
SqlCmd -E -S %servername% -Q "DROP DATABASE MyDatabase"
SET command=
SET command=%command%DECLARE @FileListTable TABLE (
SET command=%command% [LogicalName] NVARCHAR(128),
SET command=%command% [PhysicalName] NVARCHAR(260),
SET command=%command% [Type] CHAR(1),
SET command=%command% [FileGroupName] NVARCHAR(128),
SET command=%command% [Size] NUMERIC(20,0),
SET command=%command% [MaxSize] NUMERIC(20,0),
SET command=%command% [FileId] BIGINT,
SET command=%command% [CreateLSN] NUMERIC(25,0),
SET command=%command% [DropLSN] NUMERIC(25,0),
SET command=%command% [UniqueId] UNIQUEIDENTIFIER,
SET command=%command% [ReadOnlyLSN] NUMERIC(25,0),
SET command=%command% [ReadWriteLSN] NUMERIC(25,0),
SET command=%command% [BackupSizeInBytes] BIGINT,
SET command=%command% [SourceBlockSize] INT,
SET command=%command% [FileGroupID] INT,
SET command=%command% [LogGroupGUID] UNIQUEIDENTIFIER,
SET command=%command% [DifferentialBaseLSN] NUMERIC(25,0),
SET command=%command% [DifferentialBaseGUID] UNIQUEIDENTIFIER,
SET command=%command% [IsReadOnly] BIT,
SET command=%command% [IsPresent] BIT,
SET command=%command% [TDEThumbprint] VARBINARY(32),
SET command=%command% [SnapshotUrl] NVARCHAR(360)
SET command=%command%);
SET command=%command%INSERT INTO @FileListTable EXEC('RESTORE FILELISTONLY FROM DISK = ''%dbfile%''');
SET command=%command%SELECT [LogicalName], [Type] FROM @fileListTable;
SET command=%command%DECLARE @LogicalNameData varchar(128), @LogicalNameLog varchar(128);
SET command=%command%SET @LogicalNameData=(SELECT LogicalName FROM @FileListTable WHERE Type='D');
SET command=%command%SET @LogicalNameLog=(SELECT LogicalName FROM @FileListTable WHERE Type='L');
SET command=%command%RESTORE DATABASE [MyDatabase] FROM DISK = N'%dbfile%' WITH FILE = 1,
SET command=%command% MOVE @LogicalNameData TO N'%datapath%\MyDatabase.mdf',
SET command=%command% MOVE @LogicalNameLog TO N'%datapath%\MyDatabase.ldf',
SET command=%command% NOUNLOAD, STATS = 10;
ECHO.
ECHO Resotring database from file ...
SqlCmd -E -S %servername% -Q "%command%"
ECHO.
ECHO Changing Owner ...
SqlCmd -E -S %servername% -d "MyDatabase" -Q "EXEC sp_changedbowner 'sa'"
ECHO.
ECHO.
IF "%isDefault%"=="false" (
PAUSE
REM timeout /t 3
)