我有一个用于恢复数据库的批处理文件。这些是我们部门以外的其他人创建的.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
逻辑文件'客户'不属于数据库' MyDatabase'。使用RESTORE FILELISTONLY列出逻辑文件名。消息3013,级别16,状态1,服务器XXXXXX,行1 RESTORE DATABASE异常终止。
如果我尝试在没有MOVE子句的情况下进行恢复,则恢复会尝试将文件放回"返回"它们最初来自哪里 - 就像包含其他人的主目录的路径一样:
消息5133,级别16,状态1,服务器XXXXXX,行1 目录查找文件" C:\ TEMP \ Not.Me \ WidgetsRUs.mdf"操作系统错误2失败(系统找不到指定的文件。)。
我希望有一种神奇的方式可以说:MOVE '*.*' TO '"%datapath%'
有什么想法吗?
答案 0 :(得分:1)
根据建议,使用 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
答案 1 :(得分:0)
基于@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
)