SQL Server自动定时备份还原到另一台服务器

10.101.10.252 服务器是生产数据库服务器,10.80.189.43 服务器是开发测试服务器,想要将 10.101.10.252 上的生产库每天早上6点备份还原到 10.80.189.43 上,操作如下:

首先在 10.101.10.252 上面创建一个 SQL Server 代理作业,以定时备份数据库,如下:

sql 复制代码
USE [msdb]
GO

/****** Object:  Job [LGJL生产库日常备份作业]    Script Date: 2025/10/10 7:56:17 ******/
BEGIN TRANSACTION
DECLARE @ReturnCode INT
SELECT @ReturnCode = 0
/****** Object:  JobCategory [[Uncategorized (Local)]]    Script Date: 2025/10/10 7:56:17 ******/
IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N'[Uncategorized (Local)]' AND category_class=1)
BEGIN
EXEC @ReturnCode = msdb.dbo.sp_add_category @class=N'JOB', @type=N'LOCAL', @name=N'[Uncategorized (Local)]'
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback

END

DECLARE @jobId BINARY(16)
EXEC @ReturnCode =  msdb.dbo.sp_add_job @job_name=N'LGJL生产库日常备份作业', 
		@enabled=1, 
		@notify_level_eventlog=2, 
		@notify_level_email=0, 
		@notify_level_netsend=0, 
		@notify_level_page=0, 
		@delete_level=0, 
		@description=N'为开发测试环境准备的数据库备份', 
		@category_name=N'[Uncategorized (Local)]', 
		@owner_login_name=N'D621F944\Administrator', @job_id = @jobId OUTPUT
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
/****** Object:  Step [创建COPY_ONLY备份]    Script Date: 2025/10/10 7:56:17 ******/
EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N'创建COPY_ONLY备份', 
		@step_id=1, 
		@cmdexec_success_code=0, 
		@on_success_action=1, 
		@on_success_step_id=0, 
		@on_fail_action=2, 
		@on_fail_step_id=0, 
		@retry_attempts=0, 
		@retry_interval=0, 
		@os_run_priority=0, @subsystem=N'TSQL', 
		@command=N'DECLARE @DBName NVARCHAR(128) = ''LGJL'';
DECLARE @DBName1 NVARCHAR(128) = ''LGJLLOG'';
DECLARE @BackupPath NVARCHAR(512) = N''\\10.101.10.252\Backup\'';
DECLARE @FileName NVARCHAR(512) = @BackupPath + @DBName + 
    ''_'' + CONVERT(NVARCHAR(8), GETDATE(), 112) + ''_'' + 
    REPLACE(CONVERT(NVARCHAR(8), GETDATE(), 108), '':'', '''') + ''.bak'';
DECLARE @FileName1 NVARCHAR(512) = @BackupPath + @DBName1 + 
    ''_'' + CONVERT(NVARCHAR(8), GETDATE(), 112) + ''_'' + 
    REPLACE(CONVERT(NVARCHAR(8), GETDATE(), 108), '':'', '''') + ''.bak'';
	SELECT @DBName;

-- 使用COPY_ONLY选项避免干扰生产环境的常规备份策略
BACKUP DATABASE @DBName
TO DISK = @FileName
WITH COPY_ONLY, COMPRESSION, STATS = 10, CHECKSUM;
BACKUP DATABASE @DBName1
TO DISK = @FileName1
WITH COPY_ONLY, COMPRESSION, STATS = 10, CHECKSUM;
', 
		@database_name=N'master', 
		@flags=0
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_update_job @job_id = @jobId, @start_step_id = 1
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_add_jobschedule @job_id=@jobId, @name=N'每日早上6点备份', 
		@enabled=1, 
		@freq_type=4, 
		@freq_interval=1, 
		@freq_subday_type=1, 
		@freq_subday_interval=0, 
		@freq_relative_interval=0, 
		@freq_recurrence_factor=0, 
		@active_start_date=20250516, 
		@active_end_date=99991231, 
		@active_start_time=60000, 
		@active_end_time=235959, 
		@schedule_uid=N'a0036edb-ab73-4721-8888-638856033112'
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @jobId, @server_name = N'(local)'
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
COMMIT TRANSACTION
GOTO EndSave
QuitWithRollback:
    IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION
EndSave:

GO



sql 复制代码
-- LGJL_20251010_060000.bak
-- LGJLLOG_20251010_060000.bak
DECLARE @DBName NVARCHAR(128) = 'LGJL';
DECLARE @DBName1 NVARCHAR(128) = 'LGJLLOG';
DECLARE @BackupPath NVARCHAR(512) = N'\\10.101.10.252\Backup\';
DECLARE @FileName NVARCHAR(512) = @BackupPath + @DBName + 
    '_' + CONVERT(NVARCHAR(8), GETDATE(), 112) + '_' + 
    REPLACE(CONVERT(NVARCHAR(8), GETDATE(), 108), ':', '') + '.bak';
DECLARE @FileName1 NVARCHAR(512) = @BackupPath + @DBName1 + 
    '_' + CONVERT(NVARCHAR(8), GETDATE(), 112) + '_' + 
    REPLACE(CONVERT(NVARCHAR(8), GETDATE(), 108), ':', '') + '.bak';
	SELECT @DBName;

-- 使用COPY_ONLY选项避免干扰生产环境的常规备份策略
BACKUP DATABASE @DBName
TO DISK = @FileName
WITH COPY_ONLY, COMPRESSION, STATS = 10, CHECKSUM;
BACKUP DATABASE @DBName1
TO DISK = @FileName1
WITH COPY_ONLY, COMPRESSION, STATS = 10, CHECKSUM;



10.101.10.252 上创建一个共享文件夹,以便 10.80.189.43 拷贝备份的数据库文件,如下:

添加 SQL_Worker 共享权限,如下:

在 10.80.189.43 上面映射网络驱动器,如下:

10.80.189.43 上面创建一个 powershell 脚本,用以从共享文件夹拷贝备份文件,如下:

powershell 复制代码
# net use F: \\10.101.10.252\Backup /user:10.101.10.252\SQL_Worker "Anfeng@2025" /persistent:no | Out-Null
$SharePath = "\\10.101.10.252\Backup"
$LocalPath = "E:\Program Files\Microsoft SQL Server\MSSQL16.MSSQLSERVER\MSSQL\Backup"
$DBName = "LGJL"
$DBName1 = "LGJLLOG"

$DateStr = Get-Date -Format "yyyyMMdd"

$FilePattern = "${DBName}_${DateStr}_*.bak"
$FilePattern1 = "${DBName1}_${DateStr}_*.bak"

$File = Get-ChildItem -Path $SharePath -Filter $FilePattern | Select-Object -First 1
$File1 = Get-ChildItem -Path $SharePath -Filter $FilePattern1 | Select-Object -First 1

if ($File) {
    $DestPath = Join-Path -Path $LocalPath -ChildPath $File.Name
    
    try {
        Copy-Item -Path $File.FullName -Destination $DestPath -Force
        Write-Output "$(Get-Date) - success copy file: $($File.Name)"
    }
    catch {
        Write-Error "$(Get-Date) - failed copy file: $_"
        exit 1
    }
}
else {
    Write-Error "$(Get-Date) - can't find file: $FilePattern"
    exit 1
}

if ($File1) {
    $DestPath1 = Join-Path -Path $LocalPath -ChildPath $File1.Name
    
    try {
        Copy-Item -Path $File1.FullName -Destination $DestPath1 -Force
        Write-Output "$(Get-Date) - success copy file: $($File1.Name)"
    }
    catch {
        Write-Error "$(Get-Date) - failed copy file: $_"
        exit 1
    }
}
else {
    Write-Error "$(Get-Date) - can't find file: $FilePattern1"
    exit 1
}

10.80.189.43 上面的任务计划程序中创建任务,如下:




10.80.189.43 上面创建一个 SQL Server 代理作业,以自动还原备份的数据库文件,如下:

sql 复制代码
USE [msdb]
GO

/****** Object:  Job [LGJL测试环境自动还原作业]    Script Date: 2025/10/10 8:19:31 ******/
BEGIN TRANSACTION
DECLARE @ReturnCode INT
SELECT @ReturnCode = 0
/****** Object:  JobCategory [[Uncategorized (Local)]]    Script Date: 2025/10/10 8:19:31 ******/
IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N'[Uncategorized (Local)]' AND category_class=1)
BEGIN
EXEC @ReturnCode = msdb.dbo.sp_add_category @class=N'JOB', @type=N'LOCAL', @name=N'[Uncategorized (Local)]'
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback

END

DECLARE @jobId BINARY(16)
EXEC @ReturnCode =  msdb.dbo.sp_add_job @job_name=N'LGJL测试环境自动还原作业', 
		@enabled=1, 
		@notify_level_eventlog=2, 
		@notify_level_email=0, 
		@notify_level_netsend=0, 
		@notify_level_page=0, 
		@delete_level=0, 
		@description=N'从生产备份还原到测试环境', 
		@category_name=N'[Uncategorized (Local)]', 
		@owner_login_name=N'sa', @job_id = @jobId OUTPUT
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
/****** Object:  Step [还原生产数据库]    Script Date: 2025/10/10 8:19:31 ******/
EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N'还原生产数据库', 
		@step_id=1, 
		@cmdexec_success_code=0, 
		@on_success_action=3, 
		@on_success_step_id=0, 
		@on_fail_action=3, 
		@on_fail_step_id=0, 
		@retry_attempts=0, 
		@retry_interval=0, 
		@os_run_priority=0, @subsystem=N'TSQL', 
		@command=N'
DECLARE @DBName NVARCHAR(128) = ''LGJL'';
DECLARE @TestDBName NVARCHAR(128) = ''LGJL''; -- 测试环境使用不同名称
DECLARE @BackupPath NVARCHAR(512) = N''E:\Program Files\Microsoft SQL Server\MSSQL16.MSSQLSERVER\MSSQL\Backup\'';
DECLARE @FileName NVARCHAR(512);

-- 查找最新的备份文件(按日期排序)
SELECT TOP 1 @FileName = @BackupPath + ''LGJL'' + ''_'' + CONVERT(VARCHAR(8), GETDATE(), 112) + ''_'' + ''060000.bak'' --physical_device_name 
FROM (
    SELECT top 1
		bs.backup_set_id,
		bs.database_name,
		bs.backup_start_date,
		bs.backup_finish_date,
		bs.type AS backup_type,
		CASE bs.type
			WHEN ''D'' THEN ''完整备份''
			WHEN ''I'' THEN ''差异备份''
			WHEN ''L'' THEN ''日志备份''
		END AS backup_type_desc,
		bs.backup_size / 1024 / 1024 AS backup_size_MB,
		bmf.physical_device_name
	FROM 
		[10.101.10.252].[msdb].[dbo].[backupset] bs
	INNER JOIN 
		[10.101.10.252].[msdb].[dbo].[backupmediafamily] bmf ON bs.media_set_id = bmf.media_set_id
	WHERE bs.database_name LIKE ''%'' + @DBName + ''%''
	ORDER BY 
		bs.backup_start_date DESC
) AS BackupFiles
ORDER BY database_name DESC;

-- 确保找到了备份文件
IF @FileName IS NULL
BEGIN
    RAISERROR(''未找到有效的备份文件'', 16, 1);
    RETURN;
END

PRINT ''正在从文件: '' + @FileName + '' 还原数据库...'';

-- 检查测试库是否存在,存在则置为单用户模式
IF DB_ID(@TestDBName) IS NOT NULL
BEGIN
    EXEC(''ALTER DATABASE '' + @TestDBName + '' SET SINGLE_USER WITH ROLLBACK IMMEDIATE'');
    
    -- 使用REPLACE选项覆盖现有数据库
    RESTORE DATABASE @TestDBName
    FROM DISK = @FileName
    WITH REPLACE, 
    MOVE ''LGJL_Data'' TO ''E:\Program Files\Microsoft SQL Server\MSSQL16.MSSQLSERVER\MSSQL\DATA\LGJL.mdf'',
    MOVE ''LGJL_Log'' TO ''E:\Program Files\Microsoft SQL Server\MSSQL16.MSSQLSERVER\MSSQL\DATA\LGJL.ldf'',
    STATS = 10, RECOVERY;
    
    EXEC(''ALTER DATABASE '' + @TestDBName + '' SET MULTI_USER'');
END
ELSE
BEGIN
    -- 数据库不存在的情况
    RESTORE DATABASE @TestDBName
    FROM DISK = @FileName
    WITH 
    MOVE ''LGJL_Data'' TO ''E:\Program Files\Microsoft SQL Server\MSSQL16.MSSQLSERVER\MSSQL\DATA\LGJL.mdf'',
    MOVE ''LGJL_Log'' TO ''E:\Program Files\Microsoft SQL Server\MSSQL16.MSSQLSERVER\MSSQL\DATA\LGJL.ldf'',
    STATS = 10, RECOVERY;
END

PRINT ''数据库还原完成'';

-- 查询备份文件逻辑名
/*
RESTORE FILELISTONLY 
FROM DISK = ''E:\Program Files\Microsoft SQL Server\MSSQL16.MSSQLSERVER\MSSQL\Backup\LGJL_20250518_060000.bak''
*/

-- 
--IF DB_ID(''LGJL'') IS NOT NULL 
--BEGIN 
--PRINT ''hello''
--END ', 
		@database_name=N'master', 
		@flags=0
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
/****** Object:  Step [还原生产数据库LGJLLOG]    Script Date: 2025/10/10 8:19:31 ******/
EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N'还原生产数据库LGJLLOG', 
		@step_id=2, 
		@cmdexec_success_code=0, 
		@on_success_action=1, 
		@on_success_step_id=0, 
		@on_fail_action=2, 
		@on_fail_step_id=0, 
		@retry_attempts=0, 
		@retry_interval=0, 
		@os_run_priority=0, @subsystem=N'TSQL', 
		@command=N'
DECLARE @DBName NVARCHAR(128) = ''LGJLLOG'';
DECLARE @TestDBName NVARCHAR(128) = ''LGJLLOG''; -- 测试环境使用不同名称
DECLARE @BackupPath NVARCHAR(512) = N''E:\Program Files\Microsoft SQL Server\MSSQL16.MSSQLSERVER\MSSQL\Backup\'';
DECLARE @FileName NVARCHAR(512);

-- 查找最新的备份文件(按日期排序)
SELECT TOP 1 @FileName = @BackupPath + ''LGJLLOG'' + ''_'' + CONVERT(VARCHAR(8), GETDATE(), 112) + ''_'' + ''060000.bak'' --physical_device_name 
FROM (
    SELECT top 1
		bs.backup_set_id,
		bs.database_name,
		bs.backup_start_date,
		bs.backup_finish_date,
		bs.type AS backup_type,
		CASE bs.type
			WHEN ''D'' THEN ''完整备份''
			WHEN ''I'' THEN ''差异备份''
			WHEN ''L'' THEN ''日志备份''
		END AS backup_type_desc,
		bs.backup_size / 1024 / 1024 AS backup_size_MB,
		bmf.physical_device_name
	FROM 
		[10.101.10.252].[msdb].[dbo].[backupset] bs
	INNER JOIN 
		[10.101.10.252].[msdb].[dbo].[backupmediafamily] bmf ON bs.media_set_id = bmf.media_set_id
	WHERE bs.database_name LIKE ''%'' + @DBName + ''%''
	ORDER BY 
		bs.backup_start_date DESC
) AS BackupFiles
ORDER BY database_name DESC;

-- 确保找到了备份文件
IF @FileName IS NULL
BEGIN
    RAISERROR(''未找到有效的备份文件'', 16, 1);
    RETURN;
END

PRINT ''正在从文件: '' + @FileName + '' 还原数据库...'';

-- 检查测试库是否存在,存在则置为单用户模式
IF DB_ID(@TestDBName) IS NOT NULL
BEGIN
    EXEC(''ALTER DATABASE '' + @TestDBName + '' SET SINGLE_USER WITH ROLLBACK IMMEDIATE'');
    
    -- 使用REPLACE选项覆盖现有数据库
    RESTORE DATABASE @TestDBName
    FROM DISK = @FileName
    WITH REPLACE, 
    MOVE ''LGJLLOG'' TO ''E:\Program Files\Microsoft SQL Server\MSSQL16.MSSQLSERVER\MSSQL\DATA\LGJLLOG.mdf'',
    MOVE ''LGJLLOG_Log'' TO ''E:\Program Files\Microsoft SQL Server\MSSQL16.MSSQLSERVER\MSSQL\DATA\LGJLLOG.ldf'',
    STATS = 10, RECOVERY;
    
    EXEC(''ALTER DATABASE '' + @TestDBName + '' SET MULTI_USER'');
END
ELSE
BEGIN
    -- 数据库不存在的情况
    RESTORE DATABASE @TestDBName
    FROM DISK = @FileName
    WITH 
    MOVE ''LGJLLOG'' TO ''E:\Program Files\Microsoft SQL Server\MSSQL16.MSSQLSERVER\MSSQL\DATA\LGJLLOG.mdf'',
    MOVE ''LGJLLOG_Log'' TO ''E:\Program Files\Microsoft SQL Server\MSSQL16.MSSQLSERVER\MSSQL\DATA\LGJLLOG.ldf'',
    STATS = 10, RECOVERY;
END

PRINT ''数据库还原完成'';

-- 查询备份文件逻辑名
/*
RESTORE FILELISTONLY 
FROM DISK = ''E:\Program Files\Microsoft SQL Server\MSSQL16.MSSQLSERVER\MSSQL\Backup\LGJLLOG_20250518_060000.bak''
*/

-- 
--IF DB_ID(''LGJLLOG'') IS NOT NULL 
--BEGIN 
--PRINT ''hello''
--END', 
		@database_name=N'master', 
		@flags=0
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_update_job @job_id = @jobId, @start_step_id = 1
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_add_jobschedule @job_id=@jobId, @name=N'每日上午6点40还原', 
		@enabled=1, 
		@freq_type=4, 
		@freq_interval=1, 
		@freq_subday_type=1, 
		@freq_subday_interval=0, 
		@freq_relative_interval=0, 
		@freq_recurrence_factor=0, 
		@active_start_date=20250516, 
		@active_end_date=99991231, 
		@active_start_time=64000, 
		@active_end_time=235959, 
		@schedule_uid=N'997b734c-3e6d-4a9b-961a-5a745a56878d'
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @jobId, @server_name = N'(local)'
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
COMMIT TRANSACTION
GOTO EndSave
QuitWithRollback:
    IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION
EndSave:
GO



sql 复制代码
DECLARE @DBName NVARCHAR(128) = 'LGJL';
DECLARE @TestDBName NVARCHAR(128) = 'LGJL'; -- 测试环境使用不同名称
DECLARE @BackupPath NVARCHAR(512) = N'E:\Program Files\Microsoft SQL Server\MSSQL16.MSSQLSERVER\MSSQL\Backup\';
DECLARE @FileName NVARCHAR(512);

-- 查找最新的备份文件(按日期排序)
SELECT TOP 1 @FileName = @BackupPath + 'LGJL' + '_' + CONVERT(VARCHAR(8), GETDATE(), 112) + '_' + '060000.bak' --physical_device_name 
FROM (
    SELECT top 1
		bs.backup_set_id,
		bs.database_name,
		bs.backup_start_date,
		bs.backup_finish_date,
		bs.type AS backup_type,
		CASE bs.type
			WHEN 'D' THEN '完整备份'
			WHEN 'I' THEN '差异备份'
			WHEN 'L' THEN '日志备份'
		END AS backup_type_desc,
		bs.backup_size / 1024 / 1024 AS backup_size_MB,
		bmf.physical_device_name
	FROM 
		[10.101.10.252].[msdb].[dbo].[backupset] bs
	INNER JOIN 
		[10.101.10.252].[msdb].[dbo].[backupmediafamily] bmf ON bs.media_set_id = bmf.media_set_id
	WHERE bs.database_name LIKE '%' + @DBName + '%'
	ORDER BY 
		bs.backup_start_date DESC
) AS BackupFiles
ORDER BY database_name DESC;

-- 确保找到了备份文件
IF @FileName IS NULL
BEGIN
    RAISERROR('未找到有效的备份文件', 16, 1);
    RETURN;
END

PRINT '正在从文件: ' + @FileName + ' 还原数据库...';

-- 检查测试库是否存在,存在则置为单用户模式
IF DB_ID(@TestDBName) IS NOT NULL
BEGIN
    EXEC('ALTER DATABASE ' + @TestDBName + ' SET SINGLE_USER WITH ROLLBACK IMMEDIATE');
    
    -- 使用REPLACE选项覆盖现有数据库
    RESTORE DATABASE @TestDBName
    FROM DISK = @FileName
    WITH REPLACE, 
    MOVE 'LGJL_Data' TO 'E:\Program Files\Microsoft SQL Server\MSSQL16.MSSQLSERVER\MSSQL\DATA\LGJL.mdf',
    MOVE 'LGJL_Log' TO 'E:\Program Files\Microsoft SQL Server\MSSQL16.MSSQLSERVER\MSSQL\DATA\LGJL.ldf',
    STATS = 10, RECOVERY;
    
    EXEC('ALTER DATABASE ' + @TestDBName + ' SET MULTI_USER');
END
ELSE
BEGIN
    -- 数据库不存在的情况
    RESTORE DATABASE @TestDBName
    FROM DISK = @FileName
    WITH 
    MOVE 'LGJL_Data' TO 'E:\Program Files\Microsoft SQL Server\MSSQL16.MSSQLSERVER\MSSQL\DATA\LGJL.mdf',
    MOVE 'LGJL_Log' TO 'E:\Program Files\Microsoft SQL Server\MSSQL16.MSSQLSERVER\MSSQL\DATA\LGJL.ldf',
    STATS = 10, RECOVERY;
END

PRINT '数据库还原完成';

-- 查询备份文件逻辑名
/*
RESTORE FILELISTONLY 
FROM DISK = 'E:\Program Files\Microsoft SQL Server\MSSQL16.MSSQLSERVER\MSSQL\Backup\LGJL_20250518_060000.bak'
*/

-- 
--IF DB_ID('LGJL') IS NOT NULL 
--BEGIN 
--PRINT 'hello'
--END 
sql 复制代码
DECLARE @DBName NVARCHAR(128) = 'LGJLLOG';
DECLARE @TestDBName NVARCHAR(128) = 'LGJLLOG'; -- 测试环境使用不同名称
DECLARE @BackupPath NVARCHAR(512) = N'E:\Program Files\Microsoft SQL Server\MSSQL16.MSSQLSERVER\MSSQL\Backup\';
DECLARE @FileName NVARCHAR(512);

-- 查找最新的备份文件(按日期排序)
SELECT TOP 1 @FileName = @BackupPath + 'LGJLLOG' + '_' + CONVERT(VARCHAR(8), GETDATE(), 112) + '_' + '060000.bak' --physical_device_name 
FROM (
    SELECT top 1
		bs.backup_set_id,
		bs.database_name,
		bs.backup_start_date,
		bs.backup_finish_date,
		bs.type AS backup_type,
		CASE bs.type
			WHEN 'D' THEN '完整备份'
			WHEN 'I' THEN '差异备份'
			WHEN 'L' THEN '日志备份'
		END AS backup_type_desc,
		bs.backup_size / 1024 / 1024 AS backup_size_MB,
		bmf.physical_device_name
	FROM 
		[10.101.10.252].[msdb].[dbo].[backupset] bs
	INNER JOIN 
		[10.101.10.252].[msdb].[dbo].[backupmediafamily] bmf ON bs.media_set_id = bmf.media_set_id
	WHERE bs.database_name LIKE '%' + @DBName + '%'
	ORDER BY 
		bs.backup_start_date DESC
) AS BackupFiles
ORDER BY database_name DESC;

-- 确保找到了备份文件
IF @FileName IS NULL
BEGIN
    RAISERROR('未找到有效的备份文件', 16, 1);
    RETURN;
END

PRINT '正在从文件: ' + @FileName + ' 还原数据库...';

-- 检查测试库是否存在,存在则置为单用户模式
IF DB_ID(@TestDBName) IS NOT NULL
BEGIN
    EXEC('ALTER DATABASE ' + @TestDBName + ' SET SINGLE_USER WITH ROLLBACK IMMEDIATE');
    
    -- 使用REPLACE选项覆盖现有数据库
    RESTORE DATABASE @TestDBName
    FROM DISK = @FileName
    WITH REPLACE, 
    MOVE 'LGJLLOG' TO 'E:\Program Files\Microsoft SQL Server\MSSQL16.MSSQLSERVER\MSSQL\DATA\LGJLLOG.mdf',
    MOVE 'LGJLLOG_Log' TO 'E:\Program Files\Microsoft SQL Server\MSSQL16.MSSQLSERVER\MSSQL\DATA\LGJLLOG.ldf',
    STATS = 10, RECOVERY;
    
    EXEC('ALTER DATABASE ' + @TestDBName + ' SET MULTI_USER');
END
ELSE
BEGIN
    -- 数据库不存在的情况
    RESTORE DATABASE @TestDBName
    FROM DISK = @FileName
    WITH 
    MOVE 'LGJLLOG' TO 'E:\Program Files\Microsoft SQL Server\MSSQL16.MSSQLSERVER\MSSQL\DATA\LGJLLOG.mdf',
    MOVE 'LGJLLOG_Log' TO 'E:\Program Files\Microsoft SQL Server\MSSQL16.MSSQLSERVER\MSSQL\DATA\LGJLLOG.ldf',
    STATS = 10, RECOVERY;
END

PRINT '数据库还原完成';

-- 查询备份文件逻辑名
/*
RESTORE FILELISTONLY 
FROM DISK = 'E:\Program Files\Microsoft SQL Server\MSSQL16.MSSQLSERVER\MSSQL\Backup\LGJLLOG_20250518_060000.bak'
*/

-- 
--IF DB_ID('LGJLLOG') IS NOT NULL 
--BEGIN 
--PRINT 'hello'
--END



相关推荐
2501_927993531 天前
SQL Server 2022安装详细教程(图文详解,非常详细)
数据库·sqlserver
山岚的运维笔记1 天前
SQL Server笔记 -- 第20章:TRY/CATCH
java·数据库·笔记·sql·microsoft·sqlserver
山岚的运维笔记2 天前
SQL Server笔记 -- 第18章:Views
数据库·笔记·sql·microsoft·sqlserver
Traced back3 天前
SQL Server 核心语法+进阶知识点大全(小白版)
数据库·sqlserver
山岚的运维笔记3 天前
SQL Server笔记 -- 第14章:CASE语句
数据库·笔记·sql·microsoft·sqlserver
松涛和鸣3 天前
70、IMX6ULL LED驱动实战
linux·数据库·驱动开发·postgresql·sqlserver
UpYoung!3 天前
【SQL Server 2019】企业级数据库系统—数据库SQL Server 2019保姆级详细图文下载安装完全指南
运维·数据库·sqlserver·运维开发·数据库管理·开发工具·sqlserver2019
知识分享小能手3 天前
SQL Server 2019入门学习教程,从入门到精通,SQL Server 2019 数据表的操作 —语法详解与实战案例(3)
数据库·学习·sqlserver
知识分享小能手4 天前
SQL Server 2019入门学习教程,从入门到精通,SQL Server 2019数据库的操作(2)
数据库·学习·sqlserver
山岚的运维笔记4 天前
SQL Server笔记 -- 第15章:INSERT INTO
java·数据库·笔记·sql·microsoft·sqlserver