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



相关推荐
小李来了!1 天前
Oracle、MySQL、SQL server介绍及有何区别
数据库·mysql·oracle·sqlserver
Leon-Ning Liu3 天前
SQL Server在ldf文件误删的情况下恢复数据库
数据库·sqlserver
姜太小白4 天前
【SQLServer】SQL Server 2022 连接证书错误解决
网络·数据库·sqlserver
gaozhiyong08135 天前
SpringBoot连接多数据源MySQL、SqlServer等(MyBatisPlus测试)
spring boot·mysql·sqlserver
源远流长jerry8 天前
dpdk19.08编译问题解决方案
数据库·postgresql·sqlserver
全栈小58 天前
【数据库】Sql Server 安装教程,一键到底,沉浸式下载安装MSSQL和SSMS
数据库·sqlserver
Msshu12311 天前
多协议快充取电芯片 支持与主板MCU共用D+D-网络可取电可与电脑传输数据
elasticsearch·sqlserver·flink·rabbitmq·storm
夏光芒11 天前
SQLSERVER数据库常用语句
数据库·sqlserver
北京_小杰子25 天前
Windows10本地安装SQLserver数据库连接的过程
数据库·windows·sqlserver·php
山岚的运维笔记1 个月前
SQL Server笔记 -- 第86章:查询存储
笔记·python·sql·microsoft·sqlserver·flask