Skip to content

03.项目三 数据库维护

📋

课前复习(5 分钟)

请同学们思考并回答以下问题,回顾上节课 SQL Server 安全管理的内容:

  • SQL Server 有哪两种身份验证模式?各自的特点是什么?
  • 登录名与数据库用户有什么区别?
  • 什么是数据库角色?db_ownerdb_datareader 分别有什么权限?
  • GRANT / REVOKE / DENY 三个权限关键字的作用分别是什么?

💡 本项目导读:数据库安全不仅包括访问控制,还包括数据的持久性保障。如果数据库文件损坏或数据被误删,如何恢复?这就是本项目要学习的——数据库维护


维度目标
知识目标掌握备份类型(完整/差异/日志);理解 RPO/RTO 核心指标;了解分离与附加的使用场景
技能目标能使用 SSMS 和 T-SQL 完成备份与还原操作;能用 BULK INSERT 批量导入 CSV 数据;能完成数据库分离与附加迁移
素养目标树立”备份是数据安全最后防线”的运维意识;养成定期备份、多副本存储的良好习惯

内容说明
重点三种备份类型的区别与组合使用完整 → 差异 → 日志的策略搭配,是企业生产环境的核心运维方案
重点BACKUP / RESTORE 的 WITH 子句参数INIT / FORMAT / NORECOVERY / RECOVERY / STOPAT 是常考、常用参数
难点多步骤还原顺序与 NORECOVERY / RECOVERY 的时机容易混淆”还原中”状态,误在中间步骤使用 WITH RECOVERY 导致还原链断裂
难点恢复模式对日志备份的影响简单恢复模式下无法做日志备份;必须先切换为完整模式
了解分离与附加 vs 备份还原的适用场景迁移用分离、灾难恢复用备份,两者用途不同不可混淆

📌 知识点1:备份策略核心指标

Section titled “📌 知识点1:备份策略核心指标”

数据库备份是防止数据丢失的最终保障,常见触发场景:硬件故障、人为误操作(误删表/数据)、软件故障、灾难事件、版本回滚。

在制定备份策略前,需理解两个核心指标:

指标全称含义示例
RPORecovery Point Objective 恢复点目标最多能接受丢失多长时间内的数据RPO = 1小时,说明最坏情况下会丢失1小时内的数据
RTORecovery Time Objective 恢复时间目标从故障发生到系统恢复上线,最多允许花多长时间RTO = 30分钟,说明必须在30分钟内让系统重新可用

两者的关系:RPO 决定备份频率,RTO 决定恢复方案的复杂度。要求越严格(RPO/RTO 越小),备份成本越高。


📌 知识点2:备份设备(Backup Device)

Section titled “📌 知识点2:备份设备(Backup Device)”

备份设备是 SQL Server 中对备份目标位置的一个逻辑命名。可以把它理解为一个”快捷方式”——给一个磁盘文件路径起一个别名,之后备份时直接用别名,而不需要每次写完整路径。

备份设备分为两类:

  • 永久设备:通过 sp_addumpdevice 注册,保存在系统表中,重启后仍存在
  • 临时设备:直接在 BACKUP 语句中用 TO DISK = '路径' 指定,不注册到系统
EXEC sp_addumpdevice '设备类型', '逻辑设备名', '物理文件路径';
参数位置参数名含义常用值
第1个参数devtype(设备类型)指定备份介质的类型'disk' = 磁盘文件(最常用);'tape' = 磁带机(已淘汰)
第2个参数logicalname(逻辑设备名)给这个备份设备起的别名,后续 BACKUP/RESTORE 语句中用此名称引用自定义,建议与数据库名相关,如 'BackupDevice_stusta'
第3个参数physicalname(物理路径)备份文件在磁盘上的实际完整路径'D:\Backup\stusta.bak'(目录必须提前存在)

相关管理语句

-- 查看所有已注册的备份设备
SELECT name AS 逻辑名, physical_name AS 物理路径, type_desc AS 类型
FROM sys.backup_devices;
-- 删除备份设备(只删除注册信息,不删除物理文件)
EXEC sp_dropdevice 'BackupDevice_stusta';
-- 若要同时删除物理文件,加第二个参数
EXEC sp_dropdevice 'BackupDevice_stusta', 'DELFILE';

🧪 实验1:创建并查看备份设备

Section titled “🧪 实验1:创建并查看备份设备”
-- 第一步:在 SSMS 中新建查询,执行以下语句创建备份设备
-- (确保 D:\Backup\ 目录已存在,否则先在文件资源管理器中新建该文件夹)
EXEC sp_addumpdevice 'disk', 'BackupDevice_stusta', 'C:\SQLbak\stusta.bak';
-- 预期结果:消息窗口显示"命令已成功完成"
-- 第二步:查看所有已注册的备份设备,确认刚才创建的设备已出现
SELECT name AS 逻辑名, physical_name AS 物理路径, type_desc AS 类型
FROM sys.backup_devices;
-- 预期结果:列表中出现 BackupDevice_stusta,对应路径 D:\Backup\stusta.bak

📌 知识点3:完整备份(Full Backup)

Section titled “📌 知识点3:完整备份(Full Backup)”

对整个数据库的全量快照,将数据库中所有的数据页、对象结构、索引全部复制到备份文件中。

  • 备份文件独立完整,单独一个文件即可还原,不依赖其他备份
  • 文件体积最大,备份耗时最长
  • 是差异备份和日志备份的必要基准,没有完整备份,另外两种备份无法独立使用
  • 形象比喻:给整个房间拍一张全景照片
BACKUP DATABASE 数据库名
TO 备份目标
WITH 选项列表;

备份目标可以是:

  • TO 逻辑设备名:使用已注册的备份设备,如 TO BackupDevice_stusta
  • TO DISK = '路径':直接指定物理文件路径,如 TO DISK = 'D:\Backup\stusta.bak'

WITH 子句常用参数

参数含义说明
FORMAT初始化介质集格式化备份介质,清除介质上所有已有备份集(比 INIT 更彻底,还会重写介质头)。第一次使用新介质时建议加此选项
INIT覆盖现有备份集覆盖介质上的所有已有备份集,从头开始写入。不加此参数则默认追加(NOINIT)到已有备份集末尾
NOINIT(默认)追加到介质末尾将新备份追加到介质上已有备份集的后面,不覆盖原有数据
NAME = '名称'备份集名称给本次备份起一个描述性名称,方便后续通过 RESTORE HEADERONLY 识别
DESCRIPTION = '说明'备份集描述对本次备份的文字说明
COMPRESSION启用压缩对备份文件进行压缩,可减少文件大小约 50%,但会增加 CPU 开销。SQL Server 2008 Enterprise 版以上支持
STATS = n进度报告每完成 n% 在消息窗口显示一条进度信息。常用值:STATS = 10(每10%报告一次)
COPY_ONLY仅复制备份执行独立备份,不影响常规备份链(差异备份基准不受影响)。用于临时备份,不干扰正常备份计划

方法一:SSMS 图形界面

🖥️

操作步骤

第一步:准备工作

  1. Win + E 打开文件资源管理器,在 D 盘根目录新建文件夹 Backup(路径:D:\Backup)。
    • ⚠️ 此目录必须提前创建,否则备份时会报”无法打开备份设备”错误。

第二步:打开备份对话框

  1. 启动 SSMS,登录窗口中服务器名填 .,选 Windows 身份验证,点击连接
  2. 在左侧对象资源管理器展开”数据库”节点,右键单击 stusta任务备份,弹出备份对话框。

第三步:配置备份参数

  1. 在”常规”标签页确认:备份类型 = 完整,备份到 = 磁盘
  2. 在”目标”列表中删除旧路径(若有),点击添加 → 输入路径 D:\Backup\stusta_full.bak → 确定。
  3. 切换到”选项”标签页:
    • 覆盖介质:选”覆盖所有现有备份集
    • 勾选”完成后验证备份
    • 压缩:选”压缩备份

第四步:执行并验证

  1. 点击确定,等待提示”备份已成功完成”。
  2. 用文件资源管理器确认 D:\Backup\stusta_full.bak 文件存在且大小 > 0。

方法二:T-SQL

-- 方式A:使用逻辑备份设备(需先创建设备,见实验1)
BACKUP DATABASE stusta
TO BackupDevice_stusta
WITH FORMAT, -- 格式化介质,清除旧备份集
INIT, -- 从头覆盖写入
NAME = 'stusta-完整备份',
COMPRESSION, -- 启用压缩
STATS = 10; -- 每10%报告进度
-- 预期结果:消息窗口出现多行"xx% 已处理",最后显示"BACKUP DATABASE 已成功处理 xxx 页"
-- 方式B:直接指定文件路径(更常用,无需预先注册设备)
BACKUP DATABASE stusta
TO DISK = 'D:\Backup\stusta_full_20240101.bak'
WITH FORMAT, INIT,
NAME = 'stusta完整备份-20240101',
DESCRIPTION = '每周全量备份',
COMPRESSION,
STATS = 10;
-- 验证备份文件内容(查看备份集信息)
RESTORE HEADERONLY FROM DISK = 'D:\Backup\stusta_full_20240101.bak';
-- 可看到:BackupName(备份名)、BackupType(1=完整)、BackupStartDate(备份时间)等信息

📌 知识点4:差异备份(Differential Backup)

Section titled “📌 知识点4:差异备份(Differential Backup)”

只备份自上一次完整备份以来发生过变化的数据页。SQL Server 内部用一张”变更位图(Differential Bitmap)“追踪每个数据页是否被修改,差异备份只打包被标记为”已变更”的页。

⚠️

关键区别:差异备份的基准永远是最近一次完整备份,而不是上一次差异备份。

因此差异备份文件会随时间逐渐增大(距完整备份越远,累计变更越多)。

还原时只需最新的那一份差异备份即可,中间的可以跳过。

  • 还原依赖:完整备份 + 最新差异备份(两步)
  • 形象比喻:完整备份拍了全景照片,差异备份每天只拍与最初全景照片的”差距”

差异备份在 BACKUP DATABASE 语句中加 WITH DIFFERENTIAL 即可,其他参数与完整备份相同:

参数含义
DIFFERENTIAL指定本次备份为差异备份。省略此参数则默认为完整备份

🧪 实验3:模拟数据变化并执行差异备份

Section titled “🧪 实验3:模拟数据变化并执行差异备份”

方法一:SSMS 图形界面

🖥️

操作步骤

前提:已有完整备份(差异备份必须有完整备份作为基准)。

第一步:模拟数据变化

  1. 启动 SSMS,连接服务器,新建查询窗口。

  2. 执行以下语句,插入一条新记录:

    USE stusta;
    INSERT INTO stu VALUES('TEST01', '测试同学', '', 25, '测试系');
    SELECT * FROM stu WHERE sno = 'TEST01';
  3. 确认返回 1 行记录,TEST01 插入成功。

第二步:打开备份对话框

  1. 在对象资源管理器中右键单击 stusta“任务”“备份” ,弹出备份对话框。

第三步:配置差异备份参数

  1. “常规” 标签页:
    • 备份类型下拉选择 “差异” (注意默认是”完整”,必须手动切换)
    • 备份到:确认选择 “磁盘”
  2. “目标” 列表中:
    • 点击 “添加” → 输入路径 D:\Backup\stusta_diff.bak确定
    • 若列表中有旧的完整备份路径,务必先选中并点击 “移除” ,只保留本次差异备份目标
  3. ⚠️ 差异备份目标路径不要使用与完整备份相同的文件,否则会被覆盖

第四步:配置备份选项

  1. 切换到 “选项” 标签页:
    • 覆盖介质:选 “覆盖所有现有备份集”
    • 勾选 “完成后验证备份” (可选,建议勾选)
    • 压缩:选 “压缩备份”

第五步:执行并验证

  1. 点击 “确定” ,等待提示”备份已成功完成”。
  2. 用文件资源管理器确认 D:\Backup\stusta_diff.bak 文件存在。
  3. 对比文件大小:右键查看属性,差异备份文件应明显小于完整备份文件(差异备份只备份变更页)。

第六步:验证备份类型

  1. 新建查询窗口,执行:

    RESTORE HEADERONLY FROM DISK = 'D:\Backup\stusta_diff.bak';
  2. 确认 BackupType 列值为 5(1=完整,5=差异,2=事务日志)。

方法二:T-SQL

-- 第一步:先确认已有完整备份(差异备份的基准)
-- 若还没做完整备份,先执行实验2中的完整备份语句
-- 第二步:模拟数据变化(插入新记录)
USE stusta;
INSERT INTO stu VALUES('TEST01', '测试同学', '', 25, '测试系');
SELECT * FROM stu WHERE sno = 'TEST01'; -- 确认插入成功,应返回1行
-- 第三步:执行差异备份
BACKUP DATABASE stusta
TO DISK = 'C:\SQLbak\stusta_diff.bak'
WITH DIFFERENTIAL, -- 指定为差异备份
INIT,
COMPRESSION,
STATS = 10;
-- 预期结果:消息显示"BACKUP DATABASE WITH DIFFERENTIAL 已成功处理 xxx 页"
-- 注意:差异备份文件通常远小于完整备份文件
-- 第四步:查看备份集信息,确认备份类型
RESTORE HEADERONLY FROM DISK = 'C:\SQLbak\stusta_diff.bak';
-- BackupType = 5 表示差异备份(1=完整,5=差异,2=事务日志)

📌 知识点5:事务日志备份(Transaction Log Backup)

Section titled “📌 知识点5:事务日志备份(Transaction Log Backup)”

SQL Server 在执行每一条写操作(INSERT / UPDATE / DELETE)时,会先将操作的详细记录写入事务日志文件(.ldf) ,然后再修改实际数据。事务日志相当于一本操作流水账

时间戳 操作类型 操作内容
10:00:01 INSERT stu 表插入 ('S001','张三','',20,'计算机系')
10:00:05 UPDATE stu sno='S001' age 改为 21
10:01:30 DELETE 删除 course 表中 cno='C003' 的记录
10:02:00 COMMIT 提交事务

事务日志备份就是把这本账中自上次日志备份以来新增的记录打包保存,因此文件非常小。

核心价值——时间点还原:还原时按顺序”回放”日志,可精确恢复到任意时间点(精确到秒)。

  • 形象比喻:就像一段监控录像,可以”倒带”到任意时刻

前提条件:事务日志备份要求数据库处于完整恢复模式(Full Recovery Model)

在简单恢复模式下,SQL Server 会在检查点后自动截断日志,无法做日志备份。

恢复模式日志截断时机能否做日志备份适用场景
简单(Simple)检查点后自动截断,日志文件保持较小❌ 不支持开发/测试环境,可接受数据丢失
完整(Full)仅在日志备份后截断,日志会持续增长✅ 支持生产环境,要求精确时间点恢复
大容量日志(Bulk-Logged)类似完整模式✅ 支持(但不支持时间点还原)大批量导入期间临时切换,减少日志量

切换恢复模式:

-- 切换为完整恢复模式(日志备份的前提)
ALTER DATABASE stusta SET RECOVERY FULL;
-- 切换回简单模式(开发环境用,切换后日志链中断,无法再做日志还原)
ALTER DATABASE stusta SET RECOVERY SIMPLE;
-- 查看当前恢复模式
SELECT name, recovery_model_desc FROM sys.databases WHERE name = 'stusta';
BACKUP LOG 数据库名
TO 备份目标
WITH 选项列表;
参数含义说明
INIT覆盖介质上已有备份集每次日志备份建议使用独立的文件名(带时间戳),并用 INIT 覆盖,避免与同名旧日志混淆
COMPRESSION启用压缩日志文件往往较小,压缩收益不如完整备份明显,但生产环境建议开启
STATS = n进度报告同完整备份,每 n% 报告一次
NO_TRUNCATE不截断日志在数据文件损坏、无法正常访问数据库时仍能备份日志(尾日志备份场景)

🧪 实验4:切换恢复模式并执行日志备份

Section titled “🧪 实验4:切换恢复模式并执行日志备份”

方法一:SSMS 图形界面

🖥️

操作步骤

第一步:查看当前恢复模式

  1. 启动 SSMS,连接服务器,展开 “数据库” 节点。
  2. 右键单击 stusta → 选择 “属性” ,弹出数据库属性对话框。
  3. 在左侧选择 “选项” 页面。
  4. 在右侧”恢复模式”下拉框中查看当前值:
    • 若显示 FULL → 已是完整模式,跳到第三步
    • 若显示 SIMPLE → 需切换,见第二步
    • 若显示 BULK_LOGGED → 可直接做日志备份,但不支点还原

第二步:切换为完整恢复模式(如需要)

  1. 在”恢复模式”下拉框中选择 FULL

  2. 点击 “确定” ,等待提示”数据库属性更改成功”。

  3. ⚠️ 重要:切换为完整恢复模式后,必须立即执行一次完整备份,否则日志链不完整。参考实验2先做完整备份。

  4. 新建查询窗口验证:

    SELECT name, recovery_model_desc AS 恢复模式
    FROM sys.databases WHERE name = 'stusta';

    确认结果为 FULL。

第三步:模拟数据变化(供日志备份记录)

  1. 新建查询窗口:

    USE stusta;
    INSERT INTO stu VALUES('TEST02', '日志测试', '', 22, '测试系');
    SELECT * FROM stu WHERE sno = 'TEST02';
  2. 确认 TEST02 插入成功。

第四步:打开备份对话框,选择事务日志类型

  1. 右键单击 stusta“任务”“备份” ,弹出备份对话框。
  2. “常规” 标签页:
    • 备份类型下拉选择 “事务日志” (不是默认的”完整”)
    • 备份到:确认选择 “磁盘”
  3. “目标” 列表中点击 “添加” ,输入路径 D:\Backup\stusta_log1.bak,点击 确定
    • ⚠️ 建议每个日志备份使用独立的文件名(带序号或时间戳),避免互相覆盖

第五步:配置备份选项并执行第一次日志备份

  1. 切换到 “选项” 标签页:
    • 覆盖介质:选 “覆盖所有现有备份集”
    • 压缩:选 “压缩备份”
  2. 点击 “确定” ,等待提示”备份已成功完成”。

第六步:继续模拟数据变化,执行第二次日志备份

  1. 新建查询窗口:

    USE stusta;
    INSERT INTO stu VALUES('TEST03', '日志测试2', '', 23, '测试系');
  2. 再次右键 stusta“任务”“备份”

  3. 备份类型仍选 “事务日志” ,目标改为 D:\Backup\stusta_log2.bak,其他选项保持相同,点击 确定

第七步:验证日志备份结果

  1. 新建查询窗口:

    RESTORE HEADERONLY FROM DISK = 'D:\Backup\stusta_log1.bak';
    RESTORE HEADERONLY FROM DISK = 'D:\Backup\stusta_log2.bak';
  2. 确认两个文件的 BackupType 列值均为 2(2=事务日志),且备份时间符合预期。

方法二:T-SQL

-- 第一步:查看当前恢复模式
SELECT name, recovery_model_desc AS 恢复模式
FROM sys.databases
WHERE name = 'stusta';
-- 若结果为 SIMPLE,说明当前是简单模式,需要切换
-- 第二步:切换为完整恢复模式
ALTER DATABASE stusta SET RECOVERY FULL;
GO
-- 验证切换结果
SELECT name, recovery_model_desc AS 恢复模式
FROM sys.databases WHERE name = 'stusta';
-- 预期结果:recovery_model_desc 显示 FULL
-- 第三步:再次模拟数据变化(供日志备份记录)
USE stusta;
INSERT INTO stu VALUES('TEST02', '日志测试', '', 22, '测试系');
SELECT * FROM stu WHERE sno = 'TEST02';
-- 第四步:执行第一次日志备份
BACKUP LOG stusta
TO DISK = 'D:\Backup\stusta_log1.bak'
WITH INIT, COMPRESSION, STATS = 10;
-- 预期结果:消息显示"BACKUP LOG 已成功处理 xxx 页"
-- 第五步:继续变化数据,执行第二次日志备份
INSERT INTO stu VALUES('TEST03', '日志测试2', '', 23, '测试系');
BACKUP LOG stusta
TO DISK = 'D:\Backup\stusta_log2.bak'
WITH INIT, COMPRESSION, STATS = 10;
-- 第六步:验证备份集,BackupType=2 表示日志备份
RESTORE HEADERONLY FROM DISK = 'D:\Backup\stusta_log1.bak';

任务一小结

  • 完整备份:全量快照,独立可用,是另外两种备份的基准
  • 差异备份:只备份与完整备份的差量,文件小,还原需完整+最新差异两个文件
  • 日志备份:备份操作流水记录,文件最小,支持时间点精确还原,需完整恢复模式
  • 备份设备:逻辑名是物理路径的别名,sp_addumpdevice 三个参数依次是:设备类型、逻辑名、物理路径
  • FORMAT = 格式化介质;INIT = 覆盖备份集;DIFFERENTIAL = 差异备份;COMPRESSION = 压缩
  • ⚠️ 备份目录必须提前创建,日志备份前必须先切换为完整恢复模式

📌 知识点1:还原基础与 RECOVERY / NORECOVERY

Section titled “📌 知识点1:还原基础与 RECOVERY / NORECOVERY”

还原(Restore) 是将备份文件中的数据重新写回数据库的过程。SQL Server 的还原分为两个阶段:

  1. 数据还原阶段:将备份文件的数据页写入数据库文件
  2. 恢复阶段:回滚所有未提交的事务,让数据库进入一致状态,上线可用

当需要还原多个备份文件(完整 + 差异,或完整 + 多个日志)时,前面的步骤只做”数据还原”,不做”恢复”,保持等待状态以便继续追加下一个备份;最后一步才做”恢复”,让数据库上线。这就是 NORECOVERYRECOVERY 的区别。

参数含义说明
RECOVERY(默认)完成还原,数据库上线回滚未提交事务,数据库变为可用状态,还原链终止,不能再追加备份
NORECOVERY保持”正在还原”状态数据库保持”Restoring…“状态,等待追加下一个备份文件,还原链继续
STANDBY = '文件路径'只读备用状态数据库进入只读模式,可以查询数据,同时仍可继续追加日志备份(用于日志传送场景)
REPLACE强制覆盖已存在的数据库如果目标数据库已存在,默认会报错;加此参数则强制覆盖
MOVE '逻辑名' TO '路径'重定向文件路径将数据库文件还原到与备份来源不同的路径。逻辑名可通过 RESTORE FILELISTONLY 查询
STATS = n进度报告每完成 n% 在消息窗口显示一条进度信息
STOPAT = '时间'时间点还原还原日志时在指定时间点停止,只用于 RESTORE LOG,格式为 'YYYY-MM-DD HH:MM:SS'

还原前必做准备

-- 1. 查看备份文件中的数据库文件逻辑名(MOVE 子句需要)
RESTORE FILELISTONLY FROM DISK = 'D:\Backup\stusta.bak';
-- 返回结果中 LogicalName 列就是 MOVE 语句中需要的逻辑名
-- 2. 踢出其他连接,防止还原时报"数据库正在使用"错误
USE master;
ALTER DATABASE stusta SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
-- ROLLBACK IMMEDIATE:立即回滚所有正在进行的事务并断开连接
-- 3. 还原完成后恢复多用户
ALTER DATABASE stusta SET MULTI_USER;

🧪 实验5:模拟误操作并执行完整备份还原

Section titled “🧪 实验5:模拟误操作并执行完整备份还原”

方法一:SSMS 图形界面

🖥️

操作步骤

第一步:确认数据状态

  1. 启动 SSMS,连接服务器,展开 “数据库”stusta

  2. 新建查询窗口,执行以下语句确认当前数据量:

    USE stusta;
    SELECT COUNT(*) AS 当前学生数 FROM stu;
  3. 记录当前行数,作为还原前的对比基准。

第二步:模拟误操作(删除全表数据)

  1. 新建查询窗口,确认当前数据库:

    USE stusta;
    DELETE FROM stu;
    SELECT COUNT(*) AS 误删后学生数 FROM stu; -- 应显示 0
  2. 执行 DELETE FROM stu;,确认返回受影响行数,确认 SELECT COUNT(*) 结果为 0。

    • ⚠️ 此操作不可逆,正是要通过还原来修复的场景。

第三步:打开还原数据库对话框

  1. 在对象资源管理器中右键单击 stusta“任务”“还原”“数据库”
  2. 弹出 “还原数据库” 对话框。

第四步:配置还原源(定位备份文件)

  1. “源” 区域,选 “设备” ,点击右侧 “…” 按钮。
  2. “指定备份” 对话框中,点击 “添加”
  3. 在文件浏览器中导航到 D:\Backup\,选择要还原的备份文件(如 stusta_full_20240101.bak),点击 确定
  4. 回到主对话框,确认 “还原计划” 区域已列出该备份集,左侧复选框已勾选。

第五步:配置还原目标与选项

  1. 切换到 “选项” 标签页:
    • 还原到:保持默认(“至原位置”),若需要重定向文件则选”至新位置”并配置路径。
    • 覆盖现有数据库:勾选 “覆盖现有数据库” (相当于 T-SQL 的 REPLACE)。
    • 恢复状态:选 “恢复” (即 WITH RECOVERY,还原完成后数据库直接上线)。若后续还有其他备份要追加,选”不对数据库执行任何事务回滚,不允许更多还原请求”(WITH NORECOVERY)。
    • 勾选 “还原前验证备份集” (可选,增强验证)。

第六步:执行还原

  1. 点击 “确定” ,等待还原完成。
  2. 弹出提示”数据库 ‘stusta’ 的还原已成功完成”,点击 “确定”

第七步:验证还原结果

  1. 刷新对象资源管理器中的 stusta

  2. 新建查询窗口:

    USE stusta;
    SELECT COUNT(*) AS 还原后学生数 FROM stu;
    SELECT COUNT(*) AS 课程数 FROM course;
  3. 对比还原前记录的行数,确认数据已恢复。若数据与误操作前不一致,说明备份文件不是最新,需要使用其他备份。

方法二:T-SQL

-- ===== 场景:误删了全表数据,需要从完整备份还原 =====
-- 步骤1:记录还原前的数据量(基准)
USE stusta;
SELECT COUNT(*) AS 还原前学生数 FROM stu;
GO
-- 步骤2:模拟误操作——删除全表
DELETE FROM stu;
SELECT COUNT(*) AS 误删后学生数 FROM stu; -- 应为 0
GO
-- 步骤3:切换到 master 并设置单用户模式
USE master;
GO
ALTER DATABASE stusta SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
GO
-- 步骤4:查看备份文件中的逻辑文件名
RESTORE FILELISTONLY FROM DISK = 'D:\Backup\stusta.bak';
-- 记录返回的 LogicalName 列的值(如 stusta_data 和 stusta_log)
-- 步骤5:执行还原
RESTORE DATABASE stusta
FROM DISK = 'D:\Backup\stusta.bak'
WITH RECOVERY, -- 最后一步用 RECOVERY,还原完成后直接上线
MOVE 'stusta_data' TO 'D:\SQLData\stusta.mdf',
MOVE 'stusta_log' TO 'D:\SQLData\stusta_log.ldf',
REPLACE, -- 覆盖已存在的数据库
STATS = 10;
GO
-- 预期结果:消息显示"RESTORE DATABASE 已成功处理 xxx 页"
-- 步骤6:恢复多用户模式
ALTER DATABASE stusta SET MULTI_USER;
GO
-- 步骤7:验证还原结果
USE stusta;
SELECT COUNT(*) AS 还原后学生数 FROM stu;
SELECT COUNT(*) AS 课程数 FROM course;
-- 预期结果:行数与还原前一致

📌 知识点2:多步骤还原(完整 + 差异)

Section titled “📌 知识点2:多步骤还原(完整 + 差异)”

当同时拥有完整备份和差异备份时,可以用”两步还原”恢复到差异备份时刻的状态,比单独用完整备份恢复的数据更新。

还原顺序(顺序不能颠倒):

步骤1还原完整备份 WITH NORECOVERY数据库进入"正在还原"状态
步骤2还原差异备份 WITH RECOVERY数据库上线可用

最常见错误:在步骤1误用了 WITH RECOVERY,导致数据库直接上线,还原链终止,步骤2无法执行。

口诀:中间步骤全用 NORECOVERY,最后一步才用 RECOVERY。

🧪 实验6:完整 + 差异两步还原

Section titled “🧪 实验6:完整 + 差异两步还原”

方法一:SSMS 图形界面

🖥️

操作步骤

前提:已分别完成了完整备份(stusta.bak)和差异备份(stusta_diff.bak)。

第一步:打开还原数据库对话框

  1. 启动 SSMS,连接服务器。
  2. 在对象资源管理器中右键单击 stusta“任务”“还原”“数据库” ,弹出 “还原数据库” 对话框。

第二步:添加完整备份文件

  1. “源” 区域,选 “设备” ,点击右侧 “…” 按钮。
  2. “指定备份” 对话框中点击 “添加” ,找到 D:\Backup\,选择 完整备份文件(如 stusta.bak),点击 确定
  3. 返回主对话框,确认还原计划区域列出了该完整备份集,左侧复选框已勾选。
    • ⚠️ 此时不要勾选差异备份,只勾选完整备份。

第三步:执行第一次还原(完整备份,保持 NORECOVERY)

  1. 切换到 “选项” 标签页:
    • 覆盖现有数据库:勾选 “覆盖现有数据库”
    • 恢复状态:选 “不对数据库执行任何事务回滚,不允许更多还原请求” (对应 WITH NORECOVERY,保持等待状态)
  2. 点击 “确定” ,开始还原完整备份。
  3. 还原完成后,弹出提示框点击 “确定”
    • ⚠️ 还原完成后,对象资源管理器中 stusta 显示为 “stusta (正在还原…)” 状态——这是正常的,说明 NORECOVERY 生效。

第四步:追加还原差异备份(保持 NORECOVERY 后再次打开)

  1. 再次右键单击 stusta“任务”“还原”“数据库” ,重新打开还原对话框。
  2. “源” 区域点击 “设备” 右侧的 “…” 按钮。
  3. “指定备份” 对话框中点击 “添加” ,找到 D:\Backup\,选择 差异备份文件(如 stusta_diff.bak),点击 确定
  4. 返回主对话框,确认还原计划区域列出了差异备份集,左侧复选框已勾选。

第五步:执行第二次还原(差异备份,使用 RECOVERY 上线)

  1. 切换到 “选项” 标签页:
    • 覆盖现有数据库:保持勾选
    • 恢复状态:选 “恢复” (对应 WITH RECOVERY,回滚未提交事务,数据库正式上线)
  2. 点击 “确定” ,开始还原差异备份。
  3. 还原完成后,stusta 恢复正常可用状态,不再显示”正在还原…“。

第六步:验证还原结果

  1. 刷新对象资源管理器,确认 stusta 状态正常。

  2. 新建查询窗口:

    USE stusta;
    SELECT COUNT(*) AS 学生数 FROM stu;
    SELECT * FROM stu WHERE sno = 'TEST01';
  3. 预期结果:包含 TEST01 记录(差异备份中新增的数据),学生数多于仅用完整备份还原的结果。

方法二:T-SQL

-- 前提:已分别完成了完整备份(stusta.bak)和差异备份(stusta_diff.bak)
-- 步骤1:踢出其他连接
USE master;
ALTER DATABASE stusta SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
GO
-- 步骤2:还原完整备份(中间步骤,用 NORECOVERY 保持等待状态)
RESTORE DATABASE stusta
FROM DISK = 'D:\Backup\stusta.bak'
WITH NORECOVERY, -- 不上线,保持"正在还原"状态,等待追加差异备份
REPLACE,
STATS = 10;
GO
-- 预期结果:对象资源管理器中 stusta 显示为"stusta (正在还原...)"状态
-- 步骤3:追加还原差异备份(最后一步,用 RECOVERY 上线)
RESTORE DATABASE stusta
FROM DISK = 'D:\Backup\stusta_diff.bak'
WITH RECOVERY, -- 最后一步,回滚未提交事务,数据库上线
STATS = 10;
GO
-- 预期结果:消息显示"RESTORE DATABASE 已成功处理",数据库恢复正常状态
-- 步骤4:恢复多用户并验证
ALTER DATABASE stusta SET MULTI_USER;
USE stusta;
SELECT COUNT(*) AS 学生数 FROM stu;
-- 预期结果:包含差异备份时刻的数据(包括 TEST01 记录)

📌 知识点3:时间点还原(完整 + 日志)

Section titled “📌 知识点3:时间点还原(完整 + 日志)”

通过还原完整备份 + 多个连续日志备份,并在最后一步日志中指定 STOPAT 时间,可以精确恢复到任意时间点。SQL Server 在回放日志时会逐条执行操作,到达指定时间点后停止,之后的操作(包括误操作)不会被执行。

还原顺序

步骤1还原完整备份 WITH NORECOVERY
步骤2还原日志备份1 WITH NORECOVERY
步骤3还原日志备份2 WITH NORECOVERY
...
最后步骤还原最后一个日志 WITH RECOVERY, STOPAT = '指定时间点'

STOPAT 参数说明

  • 格式:STOPAT = 'YYYY-MM-DD HH:MM:SS'
  • 只能用于 RESTORE LOG(不能用于 RESTORE DATABASE
  • 指定时间必须在该日志备份覆盖的时间范围内,否则此步骤会被跳过

方法一:SSMS 图形界面

🖥️

操作步骤

前提:已有完整备份(stusta.bak)、日志备份1(stusta_log1.bak)、日志备份2(stusta_log2.bak)。场景:日志备份2中发生了误操作,需要恢复到误操作之前的时间点。

第一步:记录误操作发生前的目标时间

  1. 在执行误操作之前(或事后估算),记录要恢复到的时间点,例如 2024-01-15 14:36:59(误操作发生前约1秒)。
  2. 记录此时间,后续在还原对话框中填写。

第二步:模拟误操作(用于演示)

  1. 新建查询窗口:

    USE stusta;
    -- 记录当前时间
    SELECT GETDATE() AS 当前时间;
    -- 执行误操作(如删除测试数据)
    DELETE FROM stu WHERE sno LIKE 'TEST%';
    -- 再次记录时间,作为误操作时间参考
    SELECT GETDATE() AS 误操作时间;
  2. ⚠️ 实际生产环境中应跳过此步,直接从步骤3开始。

第三步:打开还原数据库对话框

  1. 在对象资源管理器中右键单击 stusta“任务”“还原”“数据库” ,弹出还原对话框。

第四步:添加完整备份文件(第一个备份)

  1. “源” 区域选 “设备” ,点击右侧 “…” 按钮。
  2. 点击 “添加” ,找到 D:\Backup\,选择 完整备份stusta.bak),点击 确定
  3. 返回主对话框,确认还原计划中完整备份已列出且已勾选。

第五步:添加第一个日志备份(保持 NORECOVERY)

  1. “指定备份” 对话框中再次点击 “添加” (此时对话框可能已关闭,需重新打开设备选择)。
  2. 找到 D:\Backup\,选择 日志备份1stusta_log1.bak),点击 确定
  3. 确认还原计划中同时列出了完整备份和日志备份1。

第六步:执行第一次还原(完整 + 日志1,保持 NORECOVERY)

  1. 切换到 “选项” 标签页:
    • 覆盖现有数据库:勾选 “覆盖现有数据库”
    • 恢复状态:选 “不对数据库执行任何事务回滚,不允许更多还原请求”WITH NORECOVERY
  2. 点击 “确定” ,完成第一次还原。
  3. stusta 显示 “正在还原…” 状态——正常。

第七步:添加第二个日志备份并执行时间点还原(RECOVERY + STOPAT)

  1. 再次右键 stusta“任务”“还原”“数据库”
  2. “源” 区域点击 “…” ,添加 日志备份2stusta_log2.bak),确认已勾选。
  3. 切换到 “选项” 标签页:
    • 覆盖现有数据库:保持勾选
    • 恢复状态:选 “恢复” (数据库上线)
    • “还原到” :选择 “时间点” ,点击右侧 “…” 按钮
  4. “日期和时间” 对话框中:
    • 输入目标时间(如 2024-01-15 14:36:59),或使用时间轴滑块定位到误操作前时刻
    • ⚠️ 时间必须在日志备份2覆盖的时间范围内才能生效
  5. 点击 “确定” 回到主对话框,再点击 “确定” 开始还原。

第八步:验证还原结果

  1. 刷新对象资源管理器,确认 stusta 恢复正常状态。

  2. 新建查询窗口:

    USE stusta;
    -- 检查 TEST01 和 TEST02 是否存在(误操作前插入的)
    SELECT * FROM stu WHERE sno LIKE 'TEST%';
    -- 检查 TEST03 或被删除的记录是否存在
    SELECT COUNT(*) AS 学生数 FROM stu;
  3. 预期结果:TEST01 和 TEST02 记录存在(误操作前日志备份1中提交的),TEST03 记录不存在或状态与误操作前一致,证明时间点还原成功。

方法二:T-SQL

-- 前提:已有完整备份、日志备份1(stusta_log1.bak)、日志备份2(stusta_log2.bak)
-- 场景:日志备份2中某条误操作发生在 14:37,需恢复到 14:36:59
-- 步骤1:记录误操作发生的时间
-- 在执行误操作之前记录当前时间
SELECT GETDATE() AS 当前时间; -- 记录这个时间点
-- 步骤2:模拟误操作(用于演示)
USE stusta;
DELETE FROM stu WHERE sno LIKE 'TEST%';
SELECT GETDATE() AS 误操作时间; -- 记录误操作发生的时间
-- 步骤3:踢出连接,设置单用户
USE master;
ALTER DATABASE stusta SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
GO
-- 步骤4:还原完整备份(保持 NORECOVERY)
RESTORE DATABASE stusta
FROM DISK = 'D:\Backup\stusta.bak'
WITH NORECOVERY, REPLACE, STATS = 10;
GO
-- 步骤5:还原日志备份1(保持 NORECOVERY)
RESTORE LOG stusta
FROM DISK = 'D:\Backup\stusta_log1.bak'
WITH NORECOVERY, STATS = 10;
GO
-- 步骤6:还原日志备份2,并在误操作前一秒停止
-- 将下方时间替换为步骤1中记录的"误操作前"时间
RESTORE LOG stusta
FROM DISK = 'D:\Backup\stusta_log2.bak'
WITH RECOVERY,
STOPAT = '2024-01-15 14:36:59', -- 精确到秒,误操作前一秒
STATS = 10;
GO
-- 步骤7:恢复多用户并验证
ALTER DATABASE stusta SET MULTI_USER;
USE stusta;
SELECT * FROM stu WHERE sno LIKE 'TEST%';
-- 预期结果:TEST01 和 TEST02 记录存在(误操作前插入的),TEST03 或被删除记录不存在

任务二小结

  • WITH RECOVERY:最后一步用,数据库上线,还原链终止
  • WITH NORECOVERY:中间步骤用,保持”正在还原”状态,等待追加下一个备份
  • REPLACE:覆盖已存在的数据库,还原前必须先设单用户模式
  • MOVE:重定向文件路径,逻辑名通过 RESTORE FILELISTONLY 查询
  • STOPAT:时间点还原,只用于 RESTORE LOG,格式 'YYYY-MM-DD HH:MM:SS'
  • ⚠️ 还原前必须先 USE master,否则无法踢出占用连接

📌 知识点1:数据导入导出方式概览

Section titled “📌 知识点1:数据导入导出方式概览”
方式工具特点适用场景
SSMS 向导导入和导出向导图形化,支持多种格式,无需写代码一次性少量数据迁移
BULK INSERTT-SQL 语句高性能,适合大批量 CSV/文本文件导入百万级以上数据批量导入
bcp 工具命令行工具导入导出均支持,可脚本化自动化批处理
SSISIntegration Services企业级 ETL,支持复杂数据转换复杂 ETL 流程,跨系统集成

支持的数据格式:Excel(.xls/.xlsx)、CSV/TXT 文本文件、Access、XML、另一个 SQL Server、Oracle 等。


SSMS 内置的导入导出向导(基于 SSIS 技术封装),通过图形界面引导完成数据迁移,无需编写代码,适合初学者和一次性数据迁移任务。

向导主要步骤:选数据源 → 选目标 → 选表/视图 → 配置列映射 → 执行

🖥️

操作步骤

第一步:打开导入向导

  1. 右键单击 stusta任务 → 导入数据,弹出向导窗口,点击下一步

第二步:配置数据源(Excel 文件)

  1. 数据源”下拉选择 Microsoft Excel
  2. 点击浏览,选中 student.xls 文件;Excel 版本选 Microsoft Excel 97-2003
  3. 勾选”首行包含列名称”(若 Excel 第一行是表头)。
  4. 点击下一步

第三步:配置目标(SQL Server)

  1. 目标”选 SQL Server Native Client 10.0;服务器名填 .;选 Windows 身份验证;数据库选 stusta
  2. 点击下一步

第四步:配置映射与执行

  1. 选”复制一个或多个表或视图的数据”,点击下一步
  2. 勾选要导入的 Sheet,“目标”列选对应表名(如 [dbo].[stu])。
  3. 点击编辑映射,逐列确认字段对应关系和数据类型是否正确,确认无误后点击确定
  4. 点击下一步完成,观察执行日志,确认”已传输 XX 行”且无红色错误。
  5. 点击关闭,在 SSMS 中执行 SELECT COUNT(*) FROM stu 验证数据已导入。

🖥️

操作步骤

  1. 右键单击 stusta任务 → 导出数据,点击下一步
  2. 数据源:SQL Server Native Client 10.0,服务器 .,数据库 stusta,点击下一步
  3. 目标:Microsoft Excel,文件路径输入 D:\stusta_export.xlsx,版本选 Microsoft Excel 2007-2010,点击下一步
  4. 选”复制一个或多个表或视图的数据”,勾选 [dbo].[stu][dbo].[course],点击下一步完成
  5. 用 Excel 打开 D:\stusta_export.xlsx,核对数据行数与 SQL Server 中是否一致。

📌 知识点3:BULK INSERT 批量导入

Section titled “📌 知识点3:BULK INSERT 批量导入”

BULK INSERT 是 SQL Server 提供的高性能批量数据导入语句,直接从文本文件(CSV、TXT 等)读取数据批量写入表中,跳过了常规 INSERT 语句逐行解析的开销,性能远高于逐条 INSERT,适合百万级以上的大批量数据导入。

BULK INSERT 目标表名
FROM '文件路径'
WITH (
参数列表
);
参数含义示例
FIELDTERMINATOR字段分隔符:每两个字段之间的分隔字符',' = 逗号分隔(CSV 标准);'\t' = 制表符分隔(TSV 格式);`‘

🧪 实验10:使用 BULK INSERT 批量导入 CSV

Section titled “🧪 实验10:使用 BULK INSERT 批量导入 CSV”

第一步:准备 CSV 文件

📄

  1. Win + E 打开文件资源管理器,在 C 盘新建文件夹 SQLbak(路径 C:\SQLbak)。

  2. C:\SQLbak 中新建文本文档,重命名为 students.csv(注意扩展名改为 .csv)。

  3. 右键 → 用记事本打开,输入以下内容:

    sno,sname,gender,age,dept
    S001,张三,,20,计算机系
    S002,李四,,21,信息系
    S003,王五,,22,网络系
    S004,赵六,,20,软件系
  4. 点击文件 → 另存为,编码选择 ANSI,点击保存。关闭记事本。

第二步:执行 BULK INSERT

-- 执行批量导入
USE stusta;
-- 执行批量导入
BULK INSERT stu
FROM 'C:\SQLbak\students.csv'
WITH (
FIELDTERMINATOR = ',', -- 字段间用逗号分隔(与CSV一致)
ROWTERMINATOR = '\n', -- 每行以换行符结束
FIRSTROW = 2 -- 跳过第1行表头,从第2行开始
);
-- 验证导入结果
SELECT * FROM stu ORDER BY sno;
SELECT COUNT(*) AS 导入后总行数 FROM stu;
-- 预期结果:S001~S004 四行记录出现在表中
GO
-- 验证导入结果
SELECT * FROM stu ORDER BY sno;
SELECT COUNT(*) AS 导入后总行数 FROM stu;
-- 预期结果:S001~S004 四行记录出现在表中

⚠️

常见错误排查

  • “无法批量加载,文件不存在” :检查文件路径,注意路径分隔符用反斜杠 \,不能用 /
  • 中文乱码:CSV 保存时必须选 Unicode 编码 ,SQL Server 2008 完全不支持 UTF-8 的 CODEPAGE
  • “列数不匹配” :CSV 的列数必须与 stu 表的字段数完全一致
  • 数据错位(每行数据串到下一行) :检查 ROWTERMINATOR。Windows 记事本保存的文件换行符为 '\r\n',若出现错位可尝试改为 ROWTERMINATOR = '\r\n'

任务三小结

  • SSMS向导:图形化,无需代码,适合一次性少量迁移
  • BULK INSERT:高性能,适合大批量导入。四个核心参数:FIELDTERMINATOR(字段分隔符)、ROWTERMINATOR(行终止符)、FIRSTROW(起始行)、CODEPAGE(文件编码,65001=UTF-8)
  • ⚠️ 数据错位通常是 ROWTERMINATOR 设置错误;中文乱码通常是编码不匹配

分离是将数据库从 SQL Server 实例中注销移除,但保留物理文件.mdf 数据文件和 .ldf 日志文件)。分离后,这些文件可以像普通文件一样在操作系统中复制、移动,再附加到其他 SQL Server 实例上。

操作数据库在实例中是否存在物理文件是否保留适用场景
分离(Detach)❌ 从列表消失✅ 保留物理迁移(搬到另一台服务器)
备份(Backup)✅ 继续运行✅ 原文件保留,另生成 .bak 文件数据保护、灾难恢复

重要规则:只有在数据库已分离或 SQL Server 服务已停止时,才能在操作系统中移动/复制数据库文件。

EXEC sp_detach_db '数据库名', '是否更新统计信息', '是否跳过优化检查';
参数位置参数名含义常用值
第1个参数dbname(数据库名)要分离的数据库名称'stusta'
第2个参数skipchecks(更新统计信息)分离前是否更新查询优化统计信息'true' = 更新统计信息(推荐,附加后查询性能更好);'false' = 跳过,速度更快
第3个参数keepfulltextindexfile是否保留全文索引文件通常省略,默认 NULL

方法一:SSMS 图形界面

🖥️

操作步骤

  1. 新建查询,执行以下语句确认无其他连接:

    SELECT session_id, login_name, program_name
    FROM sys.dm_exec_sessions
    WHERE database_id = DB_ID('stusta');

    若有连接,先执行:USE master; ALTER DATABASE stusta SET SINGLE_USER WITH ROLLBACK IMMEDIATE;

  2. 右键 stusta任务 → 分离,弹出分离对话框。

  3. 确认设置:删除连接(若有活动连接则勾选)、更新统计信息(建议勾选)。

  4. 确认状态列显示”就绪”后,点击确定

  5. stusta 从对象资源管理器中消失即为成功。

  6. 用文件资源管理器确认 .mdf.ldf 文件仍存在于原目录(通常为 C:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\DATA\)。

方法二:T-SQL

USE master;
GO
-- 先强制断开所有连接
ALTER DATABASE stusta SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
GO
-- 执行分离,并更新统计信息
EXEC sp_detach_db 'stusta', 'true';
GO
-- 预期结果:消息窗口显示"命令已成功完成",对象资源管理器中 stusta 消失
-- 此时可安全复制/移动 .mdf 和 .ldf 文件

附加是将已存在的数据库物理文件(.mdf + .ldf)重新载入 SQL Server 实例,使其重新出现在数据库列表中可以正常使用。附加是分离的逆操作。

推荐方式(sp_attach_db 已不推荐使用):

CREATE DATABASE 数据库名 ON
(FILENAME = '数据文件路径'),
(FILENAME = '日志文件路径')
FOR ATTACH;
参数含义说明
数据库名附加后的数据库名称可以与原名不同,相当于重命名。若与原文件名不同,需确保此名称在实例中不重复
FILENAME = '路径'数据库文件的完整物理路径第一个 FILENAME 通常是 .mdf 主数据文件,第二个是 .ldf 日志文件。路径必须使用绝对路径,文件必须已存在
FOR ATTACH指定为附加操作区别于普通的 CREATE DATABASE(新建)。若 .ldf 日志文件不存在,可用 FOR ATTACH_REBUILD_LOG 自动重建日志文件

附加前的辅助查询

-- 若不确定文件在哪里,在分离前执行此语句查看文件路径
SELECT name AS 逻辑名, physical_name AS 物理路径, type_desc AS 文件类型
FROM sys.master_files
WHERE database_id = DB_ID('stusta');

方法一:SSMS 图形界面

🖥️

操作步骤

  1. .mdf.ldf 文件确认放置在目标路径(如 D:\SQLData\)。
  2. 在对象资源管理器中右键单击”数据库”节点(非某个具体数据库),选择附加
  3. 点击添加,在文件浏览器中导航到 .mdf 文件所在目录,选中 stusta.mdf,点击确定
  4. 对话框下方自动列出关联的 .ldf 文件,确认路径正确。
    • .ldf 路径显示红色,单击该行,在下方”当前文件路径”框中手动修正路径。
  5. 可在”附加为”列修改数据库名称(不修改则使用原名 stusta)。
  6. 点击确定,刷新对象资源管理器,stusta 重新出现。

方法二:T-SQL

-- 附加数据库(文件路径需与实际位置一致)
CREATE DATABASE stusta ON
(FILENAME = 'D:\SQLData\stusta.mdf'), -- 主数据文件
(FILENAME = 'D:\SQLData\stusta_log.ldf') -- 日志文件
FOR ATTACH;
GO
-- 预期结果:消息显示"命令已成功完成",对象资源管理器中 stusta 重新出现
-- 验证附加成功
USE stusta;
SELECT COUNT(*) AS 学生数 FROM stu;
SELECT COUNT(*) AS 课程数 FROM course;
-- 附加后建议立即执行一次完整备份,保护数据
BACKUP DATABASE stusta
TO DISK = 'D:\Backup\stusta_after_attach.bak'
WITH FORMAT, INIT, COMPRESSION, STATS = 10;

任务四小结

  • 分离是”注销但不删文件”,附加是”重新注册已有文件”,两者互为逆操作
  • sp_detach_db 三个参数:数据库名、是否更新统计信息(推荐 'true')、是否保留全文索引
  • CREATE DATABASE...FOR ATTACHFILENAME 指定物理文件绝对路径,FOR ATTACH 表示附加而非新建
  • .ldf 文件丢失,用 FOR ATTACH_REBUILD_LOG 自动重建日志文件(会丢失未提交事务)
  • ⚠️ 分离后物理文件被误删则数据永久丢失;迁移完成后务必立即做完整备份

知识点核心命令关键参数
创建备份设备sp_addumpdevice设备类型 / 逻辑名 / 物理路径
完整备份BACKUP DATABASEFORMAT=格式化;INIT=覆盖;COMPRESSION=压缩;STATS=进度
差异备份BACKUP DATABASE...DIFFERENTIALDIFFERENTIAL 指定差异模式
日志备份BACKUP LOG需完整恢复模式;NO_TRUNCATE 用于损坏时尾日志备份
还原数据库RESTORE DATABASENORECOVERY=保持等待;RECOVERY=上线;REPLACE=覆盖;MOVE=重定向路径
时间点还原RESTORE LOG...STOPATSTOPAT = 'YYYY-MM-DD HH:MM:SS' 精确到秒
批量导入BULK INSERTFIELDTERMINATOR=字段分隔符;ROWTERMINATOR=行终止;FIRSTROW=起始行;CODEPAGE=编码
分离数据库sp_detach_db数据库名 / 是否更新统计信息
附加数据库CREATE DATABASE...FOR ATTACHFILENAME=物理路径;FOR ATTACH=附加模式

🏆

运维核心思想:备份不是一次性任务,而是持续的流程。生产环境中应配合 SQL Server Agent 实现自动化定期备份,并定期演练还原流程——备份不验证等于没备份。