Nis*_*ant 5 sql-server backup t-sql
我想编写一个自动化脚本来从备份文件恢复 SQL Server 数据库。然而,在 SQL 中执行此操作并不是一个简单的过程,因为主查询需要额外的输入,而这些输入实际上可以使用另一个查询来获取。我可以在一个查询中完成此操作吗?
SO 已经有一个问题;但解决方案不是很灵活。RESTORE FILELISTONLY
的定义变化非常频繁。即便如此,该解决方案似乎也非常冗长。
是否有更简单的方法将查询结果存储到变量中并使用它们?对于任何编程语言来说,这都是小菜一碟。
获取逻辑名称:
Run Code Online (Sandbox Code Playgroud)RESTORE FILELISTONLY FROM DISK = 'D:SourceBackUpFile.bak' GO
恢复数据库:
Run Code Online (Sandbox Code Playgroud)RESTORE DATABASE DBName FROM DISK = 'D:SourceBackUpFile.bak' WITH RECOVERY MOVE 'SourceMDFLogicalName' TO 'D:TargetMDFFile.mdf', MOVE 'SourceLDFLogicalName' TO 'D:TargetLDFFile.ldf'
我在SQLServerScience.com上写了一篇博客文章,展示了如何获取您想要的详细信息,并且与 2008 年以上以来的所有 SQL Server 版本兼容
这是该博客文章的主要代码:
/*
This script will generate a "RESTORE DATABASE" command with the correct "MOVE" clause, etc.
By: Hannah Vernon
*/
SET NOCOUNT ON;
DECLARE @FileListCmd nvarchar(max);
DECLARE @RestoreCmd nvarchar(max);
DECLARE @cmd nvarchar(max);
DECLARE @BackupFile nvarchar(max);
DECLARE @DBName sysname;
DECLARE @DataPath nvarchar(260);
DECLARE @LogPath nvarchar(260);
DECLARE @Version decimal(10,2);
DECLARE @MaxLogicalNameLength int;
DECLARE @MoveFiles nvarchar(max);
SET @BackupFile = N'D:\SQLServer\MyDatabaseBackup.bak'; --source backup file
SET @DBName = N'MyDB'; --target database name
SET @DataPath = N'C:\Database\Data'; --target data path
SET @LogPath = N'C:\Database\Log'; --target log path
/* ************************************
modify nothing below this point.
************************************ */
IF RIGHT(@DataPath, 1) <> '\' SET @DataPath = @DataPath + N'\';
IF RIGHT(@LogPath, 1) <> '\' SET @LogPath = @LogPath + N'\';
SET @cmd = N'';
SET @Version = CONVERT(decimal(10,2),
CONVERT(varchar(10), SERVERPROPERTY('ProductMajorVersion'))
+ '.' +
CONVERT(varchar(10), SERVERPROPERTY('ProductMinorVersion'))
);
IF @Version IS NULL --use ProductVersion instead
BEGIN
DECLARE @sv varchar(10);
SET @sv = CONVERT(varchar(10), SERVERPROPERTY('ProductVersion'));
SET @Version = CONVERT(decimal(10,2), LEFT(@sv, CHARINDEX(N'.', @sv) + 1));
END
IF OBJECT_ID(N'tempdb..#FileList', N'U') IS NOT NULL
BEGIN
DROP TABLE #FileList;
END
CREATE TABLE #FileList
(
LogicalName sysname NOT NULL
, PhysicalName varchar(255) NOT NULL
, [Type] char(1) NOT NULL
, FileGroupName sysname NULL
, Size numeric(20,0) NOT NULL
, MaxSize numeric(20,0) NOT NULL
, FileId bigint NOT NULL
, CreateLSN numeric(25,0) NOT NULL
, DropLSN numeric(25,0) NULL
, UniqueId uniqueidentifier NOT NULL
, ReadOnlyLSN numeric(25,0) NULL
, ReadWriteLSN numeric(25,0) NULL
, BackupSizeInBytes bigint NOT NULL
, SourceBlockSize int NOT NULL
, FileGroupId int NULL
, LogGroupGUID uniqueidentifier NULL
, DifferentialBaseLSN numeric(25,0) NULL
, DifferentialBaseGUID uniqueidentifier NOT NULL
, IsReadOnly bit NOT NULL
, IsPresent bit NOT NULL
);
IF @Version >= 10.5 ALTER TABLE #FileList ADD TDEThumbprint varbinary(32) NULL;
IF @Version >= 12 ALTER TABLE #FileList ADD SnapshotURL nvarchar(360) NULL;
SET @FileListCmd = N'RESTORE FILELISTONLY FROM DISK = N''' + @BackupFile + N''';';
INSERT INTO #FileList
EXEC (@FileListCmd);
SET @MaxLogicalNameLength = COALESCE((SELECT MAX(LEN(fl.LogicalName)) FROM #FileList fl), 0);
SELECT @MoveFiles = (SELECT N', MOVE N''' + fl.LogicalName + N''' '
+ REPLICATE(N' ', @MaxLogicalNameLength - LEN(fl.LogicalName))
+ N'TO N''' + CASE WHEN fl.Type = 'L' THEN @LogPath ELSE @DataPath END
+ @DBName + N'\' + CASE WHEN fl.FileGroupName = N'PRIMARY' THEN N'System'
WHEN fl.FileGroupName IS NULL THEN N'Log'
ELSE fl.FileGroupName END
+ N'\' + fl.LogicalName + CASE WHEN fl.Type = 'L' THEN N'.log'
ELSE
CASE WHEN fl.FileGroupName = N'PRIMARY' THEN N'.mdf'
ELSE N'.ndf'
END
END + N'''
'
FROM #FileList fl
FOR XML PATH(''));
SET @MoveFiles = REPLACE(@MoveFiles, N'
', N'');
SET @MoveFiles = REPLACE(@MoveFiles, char(10), char(13) + char(10));
SET @MoveFiles = LEFT(@MoveFiles, LEN(@MoveFiles) - 2);
SET @RestoreCmd = N'RESTORE DATABASE ' + @DBName + N'
FROM DISK = N''' + @BackupFile + N'''
WITH REPLACE
, RECOVERY
, STATS = 5
' + @MoveFiles + N';
GO';
IF LEN(@RestoreCmd) > 4000
BEGIN
DECLARE @CurrentLen int;
SET @CurrentLen = 1;
WHILE @CurrentLen <= LEN(@RestoreCmd)
BEGIN
PRINT SUBSTRING(@RestoreCmd, @CurrentLen, 4000);
SET @CurrentLen = @CurrentLen + 4000;
END
RAISERROR (N'Output is chunked into 4,000 char pieces - look for errant line endings!', 14, 1);
END
ELSE
BEGIN
PRINT @RestoreCmd;
END
Run Code Online (Sandbox Code Playgroud)
生成的RESTORE DATABASE
命令如下所示:
RESTORE DATABASE MyDB
FROM DISK = N'D:\SQLServer\backups\MyDB.bak'
WITH REPLACE
, RECOVERY
, STATS = 5
, MOVE N'PRIMARY' TO N'C:\Database\Data\MyDB\system\PRIMARY'
, MOVE N'LOG' TO N'C:\Database\Log\MyDB\Log\LOG';
GO
Run Code Online (Sandbox Code Playgroud)
此代码也在 SQL Server 2017 的 Linux 版本上进行了测试。
你问:
是否有更简单的方法将查询结果存储到变量中并使用它们?对于任何编程语言来说,这都是小菜一碟。
这里的要求不是向变量添加值。我们需要将一组不同数据的内容提取到表中。它在概念上可能类似于从对象加载数组。然而,在 SQL Server 中,像命令一样存储命令输出结果的唯一方法RESTORE HEADERONLY
是首先将其插入表中,然后从所需的表中获取特定值。
归档时间: |
|
查看次数: |
3491 次 |
最近记录: |