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



相关推荐
韩立学长21 小时前
【开题答辩实录分享】以《制造型企业供应商档案管理系统设计与开发》为例进行答辩实录分享
sqlserver·c#
杨云龙UP2 天前
小工具大体验:rlwrap加持下的Oracle/MySQL/SQL Server命令行交互
运维·服务器·数据库·sql·mysql·oracle·sqlserver
qq_340474026 天前
3.0 labview使用SQLServer
数据库·sqlserver·labview
杨云龙UP7 天前
SQL Server数据库事务日志问题的诊断与解法(从膨胀到瘦身)
运维·数据库·sql·sqlserver·serverless
TiAmo zhang9 天前
什么是SQL Server 2019?
数据库·sqlserver
王家视频教程图书馆9 天前
docker部署mssql
docker·容器·sqlserver
jackletter10 天前
五大关系数据库(sqlserver、mysql、oracle、pgsql、sqlite)的对象名称和转义字符
mysql·postgresql·oracle·sqlserver·sqlite
满昕欢喜12 天前
SQL Server从入门到项目实践(超值版)读书笔记 27
数据库·sql·sqlserver
码农学院13 天前
MSSQL字段去掉excel复制过来的换行符
前端·数据库·sqlserver