拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

SQL Server 2022本地数据库工程实战指南

SQL Server 2022本地数据库工程实战指南

简介:本资源是太原理工大学软件工程专业《数据库概论》课程配套的完整实验报告,面向高校数据库初学者及SQL实践者,聚焦SQL Server 2016环境下数据库对象管理与核心操作能力训练。报告覆盖数据定义(CREATE/ALTER/DROP TABLE)、索引创建(唯一/聚簇索引)、视图构建(如IS_Student系别筛选视图)及DML操作(INSERT/UPDATE/SELECT多场景示例),含详细语句执行过程、约束说明与注意事项,助力读者夯实数据库建模与查询优化基础。资源为单个Word文档(.docx),大小1.69MB,内容结构清晰,含实验目的、平台配置、分步代码、结果验证及总结反思,便于对照学习与课堂复盘。已有311人下载学习,适合课程复习、实验预习或SQL实操自查。

1. 这不是“抄答案”的实验报告,而是用 SQL Server 搭建真实数据库工程能力的起点

在太原理工大学软件工程专业,《数据库概论》实验课常被学生误读为“写几条 SELECT 就交差”的环节——但翻看近年课程大纲和头歌实训平台实际题型,你会发现:从创建带约束的学生成绩表、实现跨系部选课事务控制、到用 T-SQL 编写存储过程批量处理补考数据,所有实验都锚定一个核心目标:让本科生第一次亲手把“关系模型”变成可运行、可验证、可调试的 SQL Server 实例。这不是纸上谈兵的范式转换练习,而是用 Microsoft SQL Server 2022(RTM)本地部署环境,完成从 DDL 建模 → DML 操作 → DCL 权限控制 → T-SQL 逻辑封装的全链路闭环。适合刚学完《软件工程导论》第六版第 7 章、正准备课程设计或保研面试中被问“你做过什么数据库项目”的同学——你不需要会 Python 或 Java,但必须能独立解决[08001] SSL 提供程序: 证书链是由不受信任的颁发机构颁发的这类报错,并理解为什么DEFAULT NEWID()在主键上比IDENTITY(1,1)更贴近真实业务场景。


2. 用 SQL Server 2022 (RTM) 搭建本地实验环境:从安装到 SSMS 连接验证

2.1 安装 SQL Server 2022 (RTM) - 16.0.1000.6 (x64) 的关键选项选择

太原理工大学实验室普遍采用 Windows 10/11 教育版 + SQL Server 2022 标准版(学生可免费申请 Developer 版),安装时必须避开默认全选的“功能选择”陷阱。常见翻车点是勾选了“SQL Server Reporting Services”或“Full-Text Search”,导致安装失败率飙升(尤其在校园网 DNS 不稳定环境下)。正确做法是:

  • 实例配置:选择“默认实例”(而非命名实例),避免后续连接字符串写成localhost\SQLEXPRESS这类易错格式;
  • 服务器配置:将“SQL Server 服务”与“SQL Server 代理服务”的登录账户均设为NT AUTHORITY\NETWORK SERVICE(非“内置账户”或“本地系统”),这是解决[08001] 客户端无法建立连接的底层前提;
  • 数据库引擎配置:身份验证模式必须选“混合模式(SQL Server 身份验证和 Windows 身份验证)”,并手动设置 sa 密码(至少 8 位,含大小写字母+数字,如TaYuan2024!),否则后续实验中创建登录用户、分配角色将全部卡死;
  • 忽略“Machine Learning Services”和“PolyBase”:这两项对本科实验完全冗余,且极易因 VC++ 运行库版本冲突导致安装中断。

提示:安装包体积约 3.2GB,建议提前下载离线镜像(SQL2022-SSEI-Dev.exe),避免安装中途因校园网限速断连。若提示“对秘钥无访问权限”,说明当前 Windows 用户未加入Administrators组——请右键安装程序 → “以管理员身份运行”。

2.2 配置 SSMS 18.10 连接并修复 SSL 加密报错

安装完成后,需用 SQL Server Management Studio(SSMS)18.10(非旧版 17.x)连接本地实例。但多数同学首次连接即遭遇[08001] [Microsoft][ODBC Driver 17 for SQL Server] SSL 提供程序: 证书链是由不受信任的颁发机构颁发的 (-2146893019)。这不是证书问题,而是 SQL Server 默认启用强制加密,而本地自签名证书未被 Windows 信任。血泪经验:不要去导出/导入证书,直接关掉加密即可:

-- 在 SSMS 中以 sa 登录后,执行以下命令禁用强制加密(仅限实验环境!) USE master; GO EXEC sp_configure 'show advanced options', 1; RECONFIGURE; GO EXEC sp_configure 'force encryption', 0; RECONFIGURE; GO -- 验证是否生效 SELECT name, value_in_use FROM sys.configurations WHERE name = 'force encryption';

执行后重启 SQL Server 服务(通过 Windows 服务管理器或net stop MSSQLSERVER && net start MSSQLSERVER)。此时用 SSMS 连接时,服务器名称填localhost或.,身份验证选“SQL Server 身份验证”,登录名sa,密码为你安装时设置的密码——连接成功后,对象资源管理器中应可见master、model、msdb、tempdb四个系统数据库。

注意:force encryption = 0是实验环境安全妥协方案。若课程要求演示加密连接(如头歌平台某题),需额外配置证书并修改客户端连接字符串添加Encrypt=yes;TrustServerCertificate=yes;,但该操作复杂度远超本科实验范围,此处不展开。


3. 实验报告核心模块落地:从建表约束到事务控制的 T-SQL 实战

3.1 创建符合教科书规范的“学生-课程-成绩”三表结构

《数据库概论》实验报告首项任务必是建表。但很多同学照着课本写CREATE TABLE Student (...)却忽略太原理工实际教学要求:所有主键必须用UNIQUEIDENTIFIER类型 +DEFAULT NEWID(),外键必须显式声明ON DELETE CASCADE,且每个表需含CreatedTime DATETIME2 DEFAULT GETDATE()审计字段。这是为后续课程设计(如教务系统)预留扩展性,也是区别于“玩具数据库”的关键标志。以下是标准脚本:

-- 创建 Student 表(注意:主键非 INT IDENTITY!) CREATE TABLE Student ( StudentID UNIQUEIDENTIFIER PRIMARY KEY DEFAULT NEWID(), StudentNo CHAR(10) NOT NULL UNIQUE, -- 学号固定10位,如 '2022000001' Name NVARCHAR(20) NOT NULL, Gender CHAR(2) CHECK (Gender IN ('男', '女')), BirthDate DATE, Department NVARCHAR(30), CreatedTime DATETIME2 DEFAULT GETDATE() ); -- 创建 Course 表 CREATE TABLE Course ( CourseID UNIQUEIDENTIFIER PRIMARY KEY DEFAULT NEWID(), CourseCode CHAR(8) NOT NULL UNIQUE, -- 课程代码如 'CS1001001' CourseName NVARCHAR(50) NOT NULL, Credit TINYINT CHECK (Credit BETWEEN 1 AND 6), Department NVARCHAR(30), CreatedTime DATETIME2 DEFAULT GETDATE() ); -- 创建 Score 表(外键级联删除,模拟真实业务:删课程则清空所有成绩) CREATE TABLE Score ( ScoreID UNIQUEIDENTIFIER PRIMARY KEY DEFAULT NEWID(), StudentID UNIQUEIDENTIFIER NOT NULL, CourseID UNIQUEIDENTIFIER NOT NULL, Score DECIMAL(5,2) CHECK (Score BETWEEN 0 AND 100), ExamDate DATE DEFAULT GETDATE(), CreatedTime DATETIME2 DEFAULT GETDATE(), CONSTRAINT FK_Score_Student FOREIGN KEY (StudentID) REFERENCES Student(StudentID) ON DELETE CASCADE, CONSTRAINT FK_Score_Course FOREIGN KEY (CourseID) REFERENCES Course(CourseID) ON DELETE CASCADE );

参数说明:

  • UNIQUEIDENTIFIER DEFAULT NEWID():比INT IDENTITY更符合分布式系统思维,避免主键暴露业务量(如20240001显露当年招生数),且NEWID()生成全局唯一值,适配未来可能的分库分表;
  • CHAR(10)vsVARCHAR(10):学号长度固定,用CHAR减少存储碎片,提升索引效率;
  • DATETIME2:精度达 100 纳秒,比DATETIME更精确,且兼容性优于DATETIMEOFFSET;
  • ON DELETE CASCADE:教务系统中删除一门停开课程时,自动清理关联成绩,避免孤儿数据——这是事务一致性的基础保障,而非可选项。

3.2 用 T-SQL 存储过程实现“批量补考成绩录入”业务逻辑

实验报告高阶任务常要求编写存储过程。以“某班 30 名学生补考,需统一录入 60 分并标记为补考”为例,手写 30 条INSERT易出错,且无法保证原子性。正确解法是创建带事务控制的存储过程:

CREATE PROCEDURE InsertMakeupScores @ClassID CHAR(10), -- 班级编号,如 '2022CS01' @CourseCode CHAR(8), -- 课程代码 @DefaultScore DECIMAL(5,2) = 60.00 AS BEGIN SET NOCOUNT ON; BEGIN TRY BEGIN TRANSACTION; -- 步骤1:获取课程ID(防代码输错) DECLARE @CourseID UNIQUEIDENTIFIER; SELECT @CourseID = CourseID FROM Course WHERE CourseCode = @CourseCode; IF @CourseID IS NULL THROW 50000, '课程代码不存在,请检查 CourseCode 参数', 1; -- 步骤2:获取该班级所有学生ID DECLARE @StudentIDs TABLE (StudentID UNIQUEIDENTIFIER); INSERT INTO @StudentIDs (StudentID) SELECT StudentID FROM Student WHERE LEFT(StudentNo, 6) = @ClassID; -- 学号前6位为班级号 -- 步骤3:批量插入成绩(用 MERGE 避免重复插入) MERGE Score AS target USING @StudentIDs AS source ON target.StudentID = source.StudentID AND target.CourseID = @CourseID WHEN NOT MATCHED THEN INSERT (StudentID, CourseID, Score, ExamDate) VALUES (source.StudentID, @CourseID, @DefaultScore, GETDATE()); COMMIT TRANSACTION; PRINT '补考成绩录入成功,共 ' + CAST(@@ROWCOUNT AS VARCHAR) + ' 条记录'; END TRY BEGIN CATCH ROLLBACK TRANSACTION; DECLARE @ErrorMessage NVARCHAR(4000) = ERROR_MESSAGE(); RAISERROR(@ErrorMessage, 16, 1); END CATCH END;

执行示例与验证:

-- 调用存储过程(假设班级 '2022CS01' 已有28名学生,课程 'CS1001001' 存在) EXEC InsertMakeupScores @ClassID = '2022CS01', @CourseCode = 'CS1001001'; -- 验证:查该课程补考记录 SELECT s.StudentNo, st.Name, sc.Score, sc.ExamDate FROM Score sc JOIN Student s ON sc.StudentID = s.StudentID JOIN Course c ON sc.CourseID = c.CourseID WHERE c.CourseCode = 'CS1001001' AND sc.ExamDate = CAST(GETDATE() AS DATE);

关键设计点:

  • MERGE语句替代INSERT ... SELECT:防止同一学生多次调用时重复插入;
  • THROW自定义错误:比RAISERROR更简洁,且能终止执行;
  • LEFT(StudentNo, 6) = @ClassID:利用学号编码规则(前6位=年级+专业+班级)快速定位学生,比关联班级表更高效;
  • SET NOCOUNT ON:关闭影响行数消息,避免 SSMS 输出干扰。

4. 避坑指南:太原理工实验报告中最常踩的 4 个 T-SQL 实操雷区

4.1 现象:执行INSERT INTO Student VALUES (...)报错 “列名或所提供值的数目与表定义不匹配”

原因:未显式指定列名,且表含DEFAULT字段(如CreatedTime)或IDENTITY字段(本实验中已禁用IDENTITY,但部分同学误建表)。SQL Server 要求VALUES列数必须与表列数严格一致,哪怕有DEFAULT。
解决:永远显式写出列名——INSERT INTO Student (StudentNo, Name, Gender) VALUES ('2022000001', '张三', '男');

4.2 现象:SELECT * FROM Student WHERE Name = '张三'查不到数据,但用SELECT LEN(Name), DATALENGTH(Name) FROM Student发现LEN返回 2,DATALENGTH返回 6

原因:NVARCHAR字段存入中文时,若客户端(如 SSMS)未设置SET ANSI_NULLS ON或SET QUOTED_IDENTIFIER ON,可能导致隐式转换异常;更常见的是复制粘贴时混入不可见空格(如全角空格)。
解决:用RTRIM(LTRIM(Name)) = N'张三'清洗,且所有字符串比较必须加N前缀(N'张三'),否则 SQL Server 视为VARCHAR导致 Unicode 匹配失败。

4.3 现象:创建存储过程后,执行EXEC proc_name提示 “找不到对象”

原因:未指定架构名。SQL Server 默认架构是dbo,但若在创建时写了CREATE PROCEDURE mydb.proc_name,则必须用EXEC mydb.dbo.proc_name调用;更隐蔽的是,SSMS 当前连接的数据库不是mydb,导致解析失败。
解决:创建时省略数据库名,只写CREATE PROCEDURE dbo.InsertMakeupScores;执行前确认 SSMS 左上角数据库下拉框选中目标库(如SchoolDB)。

4.4 现象:UPDATE Score SET Score = 100 WHERE StudentID = 'xxx'执行后@@ROWCOUNT返回 0,但SELECT * FROM Score WHERE StudentID = 'xxx'确实存在该记录

原因:StudentID是UNIQUEIDENTIFIER类型,传入的'xxx'是字符串,SQL Server 会尝试隐式转换。若字符串格式非法(如含非十六进制字符),转换失败返回NULL,导致WHERE条件恒假。
解决:所有UNIQUEIDENTIFIER字段的 WHERE 条件必须用CONVERT(UNIQUEIDENTIFIER, 'xxx')或CAST('xxx' AS UNIQUEIDENTIFIER)显式转换,例如:

UPDATE Score SET Score = 100 WHERE StudentID = CONVERT(UNIQUEIDENTIFIER, 'A1B2C3D4-E5F6-7890-G1H2-I3J4K5L6M7N8');

5. 实验报告进阶技巧:用查询计划验证索引有效性与慢 SQL 优化

5.1 为高频查询字段添加复合索引:不只是CREATE INDEX

实验报告常要求“优化查询性能”。但很多同学只执行CREATE INDEX IX_Student_Department ON Student(Department),却忽略真实场景:教务系统最常查的是“计算机学院男生按出生日期排序”。此时单列索引无效,必须建覆盖索引(Covering Index):

-- 创建覆盖索引:包含查询所有字段,避免 Key Lookup CREATE NONCLUSTERED INDEX IX_Student_Dep_Gender_Birth ON Student(Department, Gender) INCLUDE (Name, BirthDate, StudentNo) WITH (DROP_EXISTING = ON);

验证效果:在 SSMS 中打开“显示实际执行计划”(Ctrl+M),执行:

SELECT Name, StudentNo, BirthDate FROM Student WHERE Department = N'计算机学院' AND Gender = N'男' ORDER BY BirthDate DESC;

观察执行计划:若出现Index Seek(而非Index Scan)且无Key Lookup图标,则索引生效;若仍有Table Scan,说明Department和Gender的选择性太低(如全院90%是男生),需调整索引列顺序或增加筛选条件。

5.2 用STATISTICS IO定位 I/O 瓶颈:比“执行时间”更真实的慢 SQL

SET STATISTICS IO ON比看“耗时毫秒数”更能暴露本质问题。例如,某次实验要求“查询每门课平均分”,同学写:

SELECT c.CourseName, AVG(s.Score) FROM Course c JOIN Score s ON c.CourseID = s.CourseID GROUP BY c.CourseName;

开启STATISTICS IO后发现logical reads高达 12000+,远超数据行数。原因:Score表无CourseID索引,导致JOIN时全表扫描。解决方案:

-- 在 Score 表的外键列上建索引(必须!) CREATE NONCLUSTERED INDEX IX_Score_CourseID ON Score(CourseID);

再次执行,logical reads降至 200 以内——这才是数据库工程师真正盯的指标。

5.3 实验报告中的“性能对比表格”怎么写才专业

不要只写“优化前 2.3s,优化后 0.15s”。评审老师要看的是可复现、可验证的量化证据。按此模板填写:

查询场景执行计划类型logical readsphysical readsCPU time (ms)elapsed time (ms)索引使用
SELECT * FROM Student WHERE Department='计算机学院'Index Scan184201245无索引
同上,添加IX_Student_Dep后Index Seek12001IX_Student_Dep

我的习惯:每次优化后,用DBCC FREEPROCCACHE清空缓存再测三次取平均值,避免缓存干扰。曾因没清缓存,在头歌平台提交报告被扣分——缓存让慢 SQL “假装快”,这是最隐蔽的翻车点。希望帮到你。

本文还有配套的精品资源,点击获取

返回列表