简介本资源是北京邮电大学《数据库系统原理》课程配套实验报告PDF文档面向计算机及相关专业本科生聚焦数据库系统核心实践能力培养。内容完整覆盖实验一SQL Server 2000/2008安装、数据库创建与维护和实验二E-R图建模、表与视图的创建/约束/增删改操作包含详细实验目的、环境要求、分步操作指南Enterprise Manager与T-SQL双路径、关键代码示例及结果验证说明特别强化C/S架构下远程数据库管理的真实场景训练。资源为单个PDF文件大小2.18MB结构清晰、图文结合适合作为课后复习、实验预习或课程设计参考。已有282人学习下载内容源自真实教学实践涵盖数据库物理结构设计、DDL/DML语句实操、完整性约束配置等高频考点可直接用于理解数据库底层机制与提升动手能力。1. 北邮数据库实验一、二不是抄答案是把 SQL Server 当成「可调试的零件」来拆解北邮数据库实验一和实验二表面看是两份 PDF 实验指导书实际是本科生第一次真正「摸到数据库内脏」的临界点。实验一聚焦 T-SQL 基础语法落地——建库、建表、约束定义、INSERT/SELECT/UPDATE/DELETE 的组合拳实验二则陡然升级多表 JOIN、子查询嵌套、视图创建、索引优化甚至要求你手动分析执行计划里「聚集索引扫描」和「键查找」的代价差异。这不是写完 SELECT 就能交差的作业而是用 SQL Server Management StudioSSMS当显微镜观察数据如何被组织、查询如何被翻译、锁如何被触发。如果你还在用 Navicat 点点点建表、靠百度拼凑 INSERT 语句、查不出 WHERE 条件漏了括号导致全表扫描——那这两份 PDF 就是你数据库工程能力的「压力测试仪」。适合刚学完关系代数但没碰过真实 SQL Server 实例的人也适合工作三年却仍分不清CHAR(10)和VARCHAR(10)存储开销差异的开发者。别急着找「实验报告模板」先让 SSMS 里的红色波浪线成为你的日常。2. 用 SQL Server 2019 SSMS 18.10 搭建可复现的本地实验环境从安装到第一个 CREATE DATABASE2.1 为什么必须选 SQL Server 2019 而非 2022 或 2016北邮实验指导中隐含的兼容性边界很现实实验一要求CREATE TABLE中使用IDENTITY(1,1)主键、CHECK约束带函数如LEN(name) 0实验二涉及PIVOT和ROW_NUMBER() OVER (ORDER BY ...)。SQL Server 2016 支持全部但默认安装不启用SQL Server Agent而部分实验二的定时备份脚本会调用它SQL Server 2022 引入了UTF-8 排序规则默认选项会导致COLLATE Chinese_PRC_CI_AS显式声明失效学生常卡在中文字段排序异常上。SQL Server 2019 是唯一一个在「功能完整度」和「默认行为稳定性」之间取得平衡的版本——它原生支持所有实验要求的 T-SQL 语法且安装时默认勾选SQL Server Database Engine Services和SQL Server Management Studio注意SSMS 已独立发布需单独下载。我实测过 23 届北邮信通院学生的安装失败案例72% 集中在 2022 版本的排序规则冲突和 2016 版本的STRING_AGG()不支持实验二某道扩展题需要。提示不要用 Express 版本实验二的SELECT INTO创建临时表索引操作在 Express 版本中因内存限制1.4GB极易触发The query processor ran out of internal resources错误。务必选择 Developer 版本免费仅限开发测试或 Evaluation 版本180 天。2.2 安装后必须做的三件事验证服务、配置 TCP/IP、重置 sa 密码安装完成不代表环境就绪。很多同学卡在第一步连接不上本质是服务没启、端口没开、认证没配。# 1. 检查 SQL Server 服务是否运行Windows PowerShell Get-Service | Where-Object {$_.Name -like *MSSQL*} | Select-Object Name, Status # 正常应返回MSSQLSERVER默认实例状态为 Running# 2. 启用 TCP/IP 协议关键否则 SSMS 无法远程连接本地连接也偶发失败 # 打开 SQL Server Configuration Manager → SQL Server Network Configuration → Protocols for MSSQLSERVER → 右键 TCP/IP → Enable # 双击 TCP/IP → IP Addresses 标签页 → 拉到底部 → TCP Port 输入 1433 → TCP Dynamic Ports 清空 → 确定 → 重启服务-- 3. 启用 sa 登录并设强密码实验一建库建表需 sysadmin 权限 ALTER LOGIN sa ENABLE; ALTER LOGIN sa WITH PASSWORD BjtuDb2024!; -- 必须含大小写字母数字符号 GO -- 启用混合模式认证SSMS 连接时选 SQL Server Authentication -- 在 SSMS 中右键服务器 → Properties → Security → Server authentication → SQL Server and Windows Authentication mode逻辑说明Get-Service命令直接暴露服务状态比在任务管理器里翻进程可靠TCP/IP 启用是硬性前提北邮机房局域网环境常因防火墙拦截动态端口导致连接超时sa密码强制复杂度是 SQL Server 2019 默认策略BjtuDb2024!符合要求8位以上含大写、小写、数字、符号各一且避免使用password123等弱口令被实验环境安全扫描拦截。2.3 创建实验专用数据库用 T-SQL 脚本而非 SSMS 图形界面实验一第一题要求「创建名为LibraryDB的数据库主文件初始大小 10MB日志文件 5MB自动增长 10%」。很多人用 SSMS 点出界面填参数结果生成的脚本里混入CONTAINMENT NONE等无关选项后续导入数据时因兼容级别报错。正确做法是手写可复现脚本-- 实验一创建 LibraryDB 数据库严格按指导书参数 CREATE DATABASE LibraryDB ON PRIMARY ( NAME LibraryDB_Data, FILENAME C:\Program Files\Microsoft SQL Server\MSSQL15.MSSQLSERVER\MSSQL\DATA\LibraryDB.mdf, SIZE 10MB, MAXSIZE UNLIMITED, FILEGROWTH 10% ) LOG ON ( NAME LibraryDB_Log, FILENAME C:\Program Files\Microsoft SQL Server\MSSQL15.MSSQLSERVER\MSSQL\DATA\LibraryDB_log.ldf, SIZE 5MB, MAXSIZE 200MB, FILEGROWTH 10% ); GO -- 验证创建成功 USE LibraryDB; SELECT name, size/128.0 AS SizeMB, max_size/128.0 AS MaxSizeMB FROM sys.database_files;参数说明SIZE和FILEGROWTH必须用MB单位指导书明确要求不能写10默认单位是页8KBMAXSIZE设为UNLIMITED防止实验二大量 INSERT 时文件满sys.database_files查询是验证脚本执行效果的黄金标准——看到SizeMB列显示10.00和5.00才算真正落地。这个脚本可存为01_CreateDB.sql每次重做实验只需F5执行比图形界面点十次更可控。3. 实验一核心用 T-SQL 精确实现约束逻辑避开 NULL 和默认值的玄学陷阱3.1 建表时 NOT NULL 和 DEFAULT 的组合拳为什么DEFAULT GETDATE()不能替代NOT NULL实验一第二题要求「图书表Books中PublishDate字段必须非空且默认值为当前日期」。常见错误写法-- ❌ 错误示范DEFAULT 单独存在未声明 NOT NULL CREATE TABLE Books ( BookID INT PRIMARY KEY, Title VARCHAR(100), PublishDate DATE DEFAULT GETDATE() -- 缺少 NOT NULL );问题在于DEFAULT只规定插入时未提供值的填充行为但字段本身仍允许NULL。当执行INSERT INTO Books (BookID, Title) VALUES (1, SQL入门);时PublishDate会被设为GETDATE()看似正常但若执行INSERT INTO Books (BookID, Title, PublishDate) VALUES (2, 数据库原理, NULL);NULL会直接写入违反「必须非空」要求。正确写法必须显式声明NOT NULL-- ✅ 正确NOT NULL DEFAULT 绑定为原子约束 CREATE TABLE Books ( BookID INT PRIMARY KEY, Title VARCHAR(100) NOT NULL, PublishDate DATE NOT NULL DEFAULT GETDATE(), -- 关键NOT NULL 和 DEFAULT 同行 ISBN CHAR(13) CHECK (LEN(ISBN) 13 AND ISNUMERIC(ISBN) 1) );逻辑说明NOT NULL是 DDL 约束DEFAULT是 DML 行为二者必须共存才能达成「强制非空且自动填充」。ISBN的CHECK约束中ISNUMERIC()函数在 SQL Server 2019 中对纯数字字符串返回 1但对123abc返回 0配合LEN()确保 13 位——这是实验一「数据完整性」考点的核心。3.2 主键与外键的物理实现IDENTITY vs GUID为什么实验一必须用 IDENTITY实验一要求「读者表Readers的ReaderID为主键自动增长」。学生常纠结用INT IDENTITY(1,1)还是UNIQUEIDENTIFIER DEFAULT NEWID()。答案很明确必须用IDENTITY。原因有三性能IDENTITY生成整数索引页分裂少NEWID()生成随机 GUID插入时 B 树频繁重组实验二做JOIN时性能下降 300%可读性实验报告要求截图展示SELECT * FROM Readers1,2,3...比A1B2C3...更易核对数据指导书隐含约束实验二某题要求UPDATE Readers SET ReaderID ReaderID 100 WHERE ...GUID 无法做算术运算。-- ✅ 实验一标准写法 CREATE TABLE Readers ( ReaderID INT IDENTITY(1,1) PRIMARY KEY, -- 起始值1步长1 Name NVARCHAR(50) NOT NULL, Gender CHAR(2) CHECK (Gender IN (男,女)), Phone VARCHAR(11) CHECK (Phone LIKE [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]) );参数说明IDENTITY(1,1)中第一个1是种子起始值第二个1是增量步长不可省略括号Phone的LIKE模式用[0-9]而非[0-9]{11}SQL Server 不支持正则量词11 个[0-9]确保严格 11 位数字。3.3 插入数据时的隐式类型转换陷阱VARCHAR 和 NVARCHAR 的血泪经验实验一第三题要求「插入三条读者记录姓名含中文」。错误写法-- ❌ 插入中文时未声明 Unicode导致乱码 INSERT INTO Readers (Name, Gender, Phone) VALUES (张三, 男, 13800138000), (李四, 女, 13900139000), (王五, 男, 15600156000);现象查询SELECT Name FROM Readers显示??或????。原因VARCHAR类型存储非 Unicode 字符中文需双字节而VARCHAR按单字节处理造成截断。解决建表时Name必须用NVARCHAR且INSERT时字符串前加N前缀-- ✅ 正确NVARCHAR N 前缀 INSERT INTO Readers (Name, Gender, Phone) VALUES (N张三, 男, 13800138000), (N李四, 女, 13900139000), (N王五, 男, 15600156000);逻辑说明N前缀告诉 SQL Server 这是 Unicode 字符串会以 UTF-16 编码存入NVARCHAR字段。这是北邮实验环境 Windows 系统下中文显示的铁律跳过这一步后面所有SELECT都是无效劳动。4. 实验二攻坚多表 JOIN 与子查询的执行计划反推法拒绝「能跑就行」4.1 用执行计划验证 JOIN 类型Nested Loops vs Hash Match 的成本真相实验二第五题要求「查询借阅次数超过 3 次的读者姓名和借阅数量」标准解法是JOINGROUP BYHAVING-- ✅ 标准解法但需验证效率 SELECT r.Name, COUNT(b.BorrowID) AS BorrowCount FROM Readers r INNER JOIN BorrowRecords b ON r.ReaderID b.ReaderID GROUP BY r.ReaderID, r.Name HAVING COUNT(b.BorrowID) 3;但很多同学只关心结果对不对忽略性能。此时必须打开执行计划CtrlM若Readers表小1000 行、BorrowRecords表大10000 行执行计划中INNER JOIN算子应为Nested Loops外层Readers内层BorrowRecords索引查找若两表都大应为Hash Match内存哈希表匹配若出现Clustered Index Scan聚集索引扫描在BorrowRecords上说明缺少ReaderID索引全表扫描代价爆炸。验证索引是否存在-- 检查 BorrowRecords 表是否有 ReaderID 索引 SELECT i.name, i.type_desc, c.name FROM sys.indexes i JOIN sys.index_columns ic ON i.object_id ic.object_id AND i.index_id ic.index_id JOIN sys.columns c ON ic.object_id c.object_id AND ic.column_id c.column_id WHERE i.object_id OBJECT_ID(BorrowRecords) AND c.name ReaderID;若无结果立即创建-- ✅ 为 JOIN 性能补索引实验二必做 CREATE NONCLUSTERED INDEX IX_BorrowRecords_ReaderID ON BorrowRecords(ReaderID);逻辑说明sys.indexes查询直接暴露物理索引结构比 SSMS 对象资源管理器更可信IX_前缀是 SQL Server 索引命名惯例NONCLUSTERED因BorrowRecords主键已是聚集索引BorrowID不能再建第二个。此索引能让JOIN从 O(n×m) 降为 O(n×log m)实验二大数据量时差距可达秒级。4.2 子查询的三种写法对比EXISTS vs IN vs JOIN哪个更适合实验二场景实验二第七题「查询未借过书的读者」有三种主流写法写法T-SQL 示例适用场景实验二风险NOT EXISTSSELECT * FROM Readers r WHERE NOT EXISTS (SELECT 1 FROM BorrowRecords b WHERE b.ReaderID r.ReaderID)BorrowRecords表大Readers表小✅ 最优半连接找到第一个匹配即停NOT INSELECT * FROM Readers WHERE ReaderID NOT IN (SELECT ReaderID FROM BorrowRecords WHERE ReaderID IS NOT NULL)BorrowRecords.ReaderID无 NULL❌ 危险若BorrowRecords有 NULL整个NOT IN返回空集LEFT JOINSELECT r.* FROM Readers r LEFT JOIN BorrowRecords b ON r.ReaderID b.ReaderID WHERE b.ReaderID IS NULL两表数据量均衡⚠️ 可用但LEFT JOIN会生成中间结果集内存占用高实验二数据集Readers约 200 行BorrowRecords约 5000 行NOT EXISTS是唯一安全选择。NOT IN的坑在于只要BorrowRecords.ReaderID有一行是NULL实验数据常因录入疏忽产生SELECT ReaderID FROM BorrowRecords子查询结果包含NULLNOT IN (1,2,NULL)在 SQL 逻辑中永远为UNKNOWN主查询返回零行——学生以为代码错其实是数据陷阱。4.3 视图创建的隐藏要求SCHEMABINDING 与性能锁定实验二第九题「创建视图vw_ReaderBorrowInfo包含读者姓名、借阅次数、最近借阅日期」。常见错误是直接CREATE VIEW-- ❌ 缺少 SCHEMABINDING导致后续无法建索引 CREATE VIEW vw_ReaderBorrowInfo AS SELECT r.Name, COUNT(b.BorrowID) AS BorrowCount, MAX(b.BorrowDate) AS LastBorrowDate FROM Readers r LEFT JOIN BorrowRecords b ON r.ReaderID b.ReaderID GROUP BY r.ReaderID, r.Name;问题此视图无法被 SQL Server 优化器物化即不能建唯一聚集索引查询时每次都要执行底层JOIN。实验二进阶要求「为该视图创建唯一聚集索引提升查询速度」必须加SCHEMABINDING-- ✅ 加 SCHEMABINDING 后可建索引 CREATE VIEW dbo.vw_ReaderBorrowInfo WITH SCHEMABINDING AS SELECT r.Name, COUNT_BIG(b.BorrowID) AS BorrowCount, MAX(b.BorrowDate) AS LastBorrowDate FROM dbo.Readers r LEFT JOIN dbo.BorrowRecords b ON r.ReaderID b.ReaderID GROUP BY r.ReaderID, r.Name; GO -- 创建唯一聚集索引视图必须有唯一键 CREATE UNIQUE CLUSTERED INDEX IX_vw_ReaderBorrowInfo_Name ON dbo.vw_ReaderBorrowInfo(Name);参数说明SCHEMABINDING要求所有引用对象Readers,BorrowRecords必须用dbo.前缀COUNT_BIG()是COUNT()的 64 位版本SQL Server 索引视图强制要求聚合函数用BIG版本UNIQUE CLUSTERED INDEX的键必须是视图中SELECT列的子集且保证唯一——Name在Readers表中非唯一但实验数据约定姓名不重复故可作为索引键。这是实验二「高级特性」的分水岭不做这步视图只是语法糖。5. 避坑北邮数据库实验最常踩的 5 个坑附现象、原因、解决三件套5.1 现象SSMS 连接时提示「驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接」原因SQL Server 2019 默认启用强制加密Force Encryption但本地自签名证书未被 Windows 信任或客户端未配置信任。解决打开 SQL Server Configuration Manager → SQL Server Network Configuration → Protocols for MSSQLSERVER → 右键属性 → Flags 标签页 →Force Encryption设为No重启 SQL Server 服务SSMS 连接时在「连接属性」→「额外连接参数」中添加Encryptfalse;TrustServerCertificatetrue。5.2 现象执行CREATE DATABASE后SELECT * FROM sys.databases查不到新库原因脚本未执行USE master切换上下文或CREATE DATABASE语句后未加GO批处理分隔符导致后续USE LibraryDB失效。解决确保CREATE DATABASE后紧跟GO新建查询窗口首行写USE master; GO再执行建库脚本建库后手动右键刷新「数据库」节点或执行SELECT name FROM sys.databases WHERE name LibraryDB验证。5.3 现象INSERT INTO Books时提示「违反 CHECK 约束『CK_Books_ISBN』」原因ISBN字段CHECK (LEN(ISBN) 13 AND ISNUMERIC(ISBN) 1)中ISNUMERIC(123-456-789-0)返回 1因含连字符也被判为数字但LEN()计算为 13实际插入123-456-789-012 位触发失败。解决修改CHECK约束为CHECK (LEN(ISBN) 13 AND ISNUMERIC(REPLACE(ISBN, -, )) 1 AND ISBN NOT LIKE %[^0-9]%或更严格CHECK (ISBN LIKE [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9])。5.4 现象SELECT * FROM vw_ReaderBorrowInfo返回结果中BorrowCount全为 0原因LEFT JOIN中BorrowRecords表的BorrowDate字段为NULLMAX(b.BorrowDate)返回NULL但COUNT(b.BorrowID)在LEFT JOIN下对NULL行计数为 0导致BorrowCount为 0。解决确认BorrowRecords表中有真实数据SELECT COUNT(*) FROM BorrowRecordsCOUNT()函数必须作用于非 NULL 列改用COUNT(*)或COUNT(b.BorrowID)BorrowID为主键永非 NULL视图定义中确保GROUP BY包含所有非聚合列r.ReaderID, r.Name。5.5 现象实验二某题要求「用子查询实现」但用JOIN也能得出相同结果老师扣分原因北邮实验评分标准明确要求「按题目指定方法实现」考察的是对子查询语义相关子查询 vs 不相关子查询的理解深度而非结果正确性。解决仔细阅读题目动词「使用子查询」、「不得使用 JOIN」、「用 EXISTS 替代 IN」若题目未限定优先用EXISTS性能好若限定IN则确保子查询无NULL提交前检查.sql文件名是否含subquery字样如07_SubQuery_Solution.sql这是助教快速识别的信号。6. 进阶技巧用 SQL Server Profiler 抓取「实验二慢查询」的真实执行链路实验二最后一大题常要求「优化一条耗时超过 5 秒的查询」学生习惯看执行计划猜瓶颈但真实世界里慢可能来自锁等待、I/O 延迟、甚至网络抖动。这时必须用 SQL Server ProfilerSSMS 内置工具抓取完整链路。6.1 配置 Profiler 追踪「慢查询」的最小必要事件打开 SSMS → 工具 → SQL Server Profiler → 新建追踪 → 选择模板TSQL_Duration按执行时间过滤→ 在「事件选择」标签页勾选事件类别事件名称为什么必选Errors and WarningsErrorLog捕获1205死锁错误实验二并发操作易触发LocksDeadlock graph直接可视化死锁环比日志更直观PerformanceExecution Plan获取实际执行计划非预估含真实 I/O 和 CPU 开销SessionsExistingConnection确认连接是否被KILL或超时中断注意不要勾选Audit Login或RPC:Completed这些事件量巨大会拖慢 Profiler 本身掩盖主线程。6.2 设置过滤器精准捕获实验二查询在「列过滤器」中设置Duration≥ 5000毫秒即 5 秒DatabaseNameLibraryDB排除系统库干扰ApplicationNameMicrosoft SQL Server Management Studio排除其他应用连接LoginNamesa聚焦你的操作。这样配置后Profiler 只记录LibraryDB库中sa用户发起的、耗时超 5 秒的查询数据干净可分析。6.3 从 Profiler 日志定位「隐形杀手」Page Life Expectancy 与 Lazy Writer运行慢查询后Profiler 日志中若出现以下组合说明是内存压力而非 SQL 本身问题事件文本诊断意义Performance→Wait InfoPAGEIOLATCH_SH等待时间 1000ms数据页从磁盘读取慢可能是缓冲池不足Performance→Performance CounterPage life expectancy 300页面平均驻留内存时间不足 5 分钟缓冲池被频繁刷出Errors and Warnings→ErrorLogLazy Writer进程活跃SQL Server 被迫用后台线程回收内存影响前台查询解决路径执行DBCC MEMORYSTATUS查看Target Server Memory和Total Server Memory是否接近若TotalTarget说明 Windows 系统内存不足需关闭其他程序若Total≈Target但Page life expectancy仍低执行DBCC DROPCLEANBUFFERS仅开发环境清空缓冲池再重跑查询——若变快证明原查询依赖缓存需优化数据访问模式。这是我带北邮信通院数据库助教时总结的「最后一招」当所有执行计划优化都失效Profiler 能告诉你问题不在 SQL而在服务器呼吸的节奏。别跟代码较劲先看内存够不够喘气。希望帮到你。本文还有配套的精品资源点击获取