简介这份资源是太原理工大学软件工程专业「数据库概论」课程的实验报告面向正在学习数据库系统原理、需要完成SQL上机实验的本科生与自学者。报告以Microsoft SQL Server 2016为平台围绕交互式SQL语句的使用展开涵盖数据定义、索引创建、视图创建与数据操作四大模块可帮助读者对照课程要求完成建表、改表、删表、建索引、建视图及增删改查等实验任务。压缩包内共1个docx文件约1.69MB为完整实验报告文档包含实验目的、平台说明、主要实验内容及结果与总结其中给出了Student、Course、Sc、Employee等表的建表语句、索引与视图示例以及多组插入、修改数据的SQL代码便于直接参考与复现。目前已有311人学习下载适合需要梳理SQL语法、理解数据完整性与约束设置、查漏补缺的数据库初学者使用。1. 数据库实验报告到底在写什么从一份课程作业看懂 SQL 的骨架很多人第一次看到“数据库实验报告”这六个字脑子里浮现的画面大概是一叠打印纸、一堆截图还有满屏看不懂的大写英文单词。其实把它拆开看这份东西的核心就一件事用 SQL 语句跟数据库对话让它乖乖存数据、取数据、管数据。你可以把数据库想象成一个超级仓库表就是货架字段是货架上的标签而 SQL 就是你跟仓库管理员沟通的语言。这份来自某高校软件工程专业的数据库概论实验报告记录的就是一个学生从建货架、贴标签、放货物到查库存的完整过程。它之所以值得搞懂是因为不管你以后做开发、做测试还是做数据分析只要碰数据这套逻辑就绕不开。搞懂它你就拿到了跟任何数据库系统打交道的通用钥匙。2. 数据定义与完整性为什么建表不能随便写2.1 建表就像盖房子主键是地基先看实验里最基础的一步创建 Student 表。语句长这样CREATE TABLE Student( Sno CHAR(8) PRIMARY KEY, Sname CHAR(10), Ssex CHAR(2), Sage INT, Sdept CHAR(20) );这段代码在干什么通俗地说就是告诉数据库“我要建一个叫 Student 的货架第一列叫 Sno存 8 个字符它是主键。”主键是什么你可以理解成每个学生的身份证号——不能重复不能为空数据库靠它来区分“张三”和“李四”。如果没有主键你插两条一模一样的记录进去数据库也分不清谁是谁后面改数据、删数据就会翻车。实验里还建了 Course 表和 SC 表。SC 表比较特殊它的主键是(Sno, Cno)两个字段合起来。这叫复合主键意思是“一个学生选一门课”只能出现一次但同一个学生可以选多门课同一门课也可以被多个学生选。这就是多对多关系在表结构上的落地方式。注意主键选得好不好直接影响后面查询和更新的效率。实验里用学号做主键是合理的因为学号天然唯一如果用姓名做主键重名的情况就会让你头疼。2.2 约束不是摆设是数据的保险丝实验三专门讲了数据完整性里面出现了几种约束NOT NULL、CHECK、DEFAULT、FOREIGN KEY。这些东西看起来像是建表时顺手加的实际上它们是数据库的保险丝。举个例子实验里给 Ssex 字段加了CHECK(Ssex IN (男,女))。这意味着你往这个字段插“未知”或者“其他”就会被数据库直接拒绝。再比如 SC 表的 Grade 字段有CHECK(Grade 0 AND Grade 100)你插一个 120 分进去数据库会报错。这就是 CHECK 约束的作用在数据进入仓库之前先过一道安检。外键约束更关键。SC 表里的 Sno 引用了 Student 表的 SnoCno 引用了 Course 表的 Cno。这意味着你不能往 SC 表里插一个 Student 表里不存在的学号。实验里有一个检查环节尝试插入重复主键、插入空主键、修改主键值观察数据库的反应。这些操作之所以会失败正是因为约束在起作用。打个比方外键就像快递单上的收件人地址——如果地址在系统里根本不存在快递公司就不会收这个件。数据库也一样它不允许你引用一个不存在的记录。2.3 索引和视图让查询更快、让视角更清晰实验里还创建了索引和视图。索引是什么你可以把它想象成书的目录。没有目录你要找某一页只能一页一页翻有了目录直接跳到对应位置。实验里给 Course 表的 Cname 字段建了索引给 Student 表的 Sname 建了唯一索引还给 SC 表建了聚簇索引。聚簇索引比较特殊它不仅是一份目录还会改变数据在仓库里的物理摆放顺序。实验里CREATE CLUSTERED INDEX iSnoCno ON Sc(Sno, Cno DESC)的意思是SC 表里的数据按照 Sno 升序、Cno 降序来存放。这样查某个学生的选课记录时相关数据在物理上就是挨着的读取速度会快很多。视图则是一个虚拟表。实验里创建了IS_Student视图只显示计算机科学系的学生。视图本身不存数据它只是一条被保存下来的查询语句。每次你查这个视图数据库就现场执行一遍背后的 SELECT。视图的好处是你可以把复杂的多表查询包装成一个简单的名字以后直接查这个名字就行不用每次都写一长串 JOIN。提示视图不占存储空间但它依赖底层表。如果底层表被删了视图也就查不出东西了。3. 数据操作与查询增删改查背后的逻辑3.1 插入、修改、删除数据不是想动就能动实验二里有一大段是在做数据操作。插入数据用INSERT INTO修改用UPDATE删除用DELETE。这三件事看起来简单但实验里埋了不少坑。比如插入数据时实验里有一条INSERT INTO Student VALUES(20100003,刘洋,女,null,null,1001)。这里 Sage 和 Sdept 都是 null说明这两列允许为空。但如果 Sno 或者 Sname 是 NOT NULL 约束你就不能这么写。再比如修改数据时实验里有一条UPDATE Student SET SageSage1这会把所有学生的年龄都加一岁。如果你只想改某一个人就必须加 WHERE 条件否则就是全表更新——这是新手最容易踩的坑之一。删除数据也一样。实验里有一条DELETE FROM Student WHERE Sno20100022只删学号为 20100022 的那条记录。如果你写成DELETE FROM Student整张表的数据就全没了。数据库不会问你“确定吗”它直接执行。所以每次写 DELETE 和 UPDATE 之前先写 WHERE再写前面的部分这是一个值得养成的习惯。3.2 查询是重头戏从单表到多表再到子查询查询是实验里篇幅最大的部分。从最简单的SELECT * FROM Student到带条件的WHERE SdeptCS再到分组统计、连接查询、嵌套查询层层递进。单表查询里有一个容易搞混的点WHERE和HAVING的区别。实验里有一条统计各门课程选课人数的语句SELECT Cno, COUNT(*) AS 人数, AVG(Grade) AS 均分 FROM SC GROUP BY Cno HAVING AVG(Grade) 90;这里GROUP BY先把数据按课程号分组然后HAVING对分组后的结果做过滤。你不能把AVG(Grade) 90写到 WHERE 里面去因为 WHERE 是在分组之前执行的它不认识聚合函数。这是初学者最容易混淆的地方之一。连接查询是另一个重点。实验里用了两种写法一种是在 WHERE 里写连接条件另一种是用JOIN ... ON。两种写法结果一样但后者更清晰尤其是涉及多张表的时候。外连接LEFT OUTER JOIN则保证了左表的所有记录都会出现即使右表没有匹配的数据。实验里用它来查“每个学生及其选修课程的情况”即使某个学生没选课他的名字也会出现在结果里只是课程字段为 NULL。嵌套查询和集合查询属于进阶操作。IN、EXISTS、UNION、INTERSECT、EXCEPT这些关键字本质上是在用集合的思维处理数据。比如UNION就是把两个查询结果合并成一个INTERSECT是取交集EXCEPT是取差集。实验里用它们来查“计算机科学系的学生”和“年龄不大于 19 岁的学生”的并集、交集和差集。3.3 一个容易被忽略的细节空值处理实验里有一条查询是SELECT Sno, Cno FROM SC WHERE Score IS NULL。这里用的是IS NULL不是 NULL。为什么因为在 SQL 里NULL 表示“未知”它不等于任何值也不等于另一个 NULL。你用 NULL去比较结果永远是 false。这是一个非常经典的坑很多人第一次写的时候都会写成 NULL然后发现查不出任何数据。注意空值在统计时也会被忽略。比如AVG(Score)计算平均分时NULL 的行不会参与计算。如果你希望 NULL 按 0 处理需要用ISNULL或COALESCE函数转换。4. 常见误区与易混概念这些坑你大概率会踩4.1 DELETE 和 DROP 的区别这是最经典的一组易混概念。DELETE FROM Student是删除表里的数据表结构还在你可以继续往里插数据。DROP TABLE Student是把整张表连结构带数据一起删掉删完之后这张表就不存在了。实验里用的是 DELETE因为后面还要继续查数据。如果你误用了 DROP整个实验就得重做。区分方法很简单DELETE 是“清空货架上的货”DROP 是“把货架也拆了”。4.2 WHERE 和 HAVING 的执行顺序前面提过WHERE 在分组之前过滤HAVING 在分组之后过滤。实验里有一条HAVING AVG(Grade) 90如果你把它写成WHERE AVG(Grade) 90数据库会直接报错因为 WHERE 不认识聚合函数。记住一句话WHERE 管的是“哪些行参与分组”HAVING 管的是“哪些组留下来”。4.3 主键约束和唯一约束的差别实验里给 Course 表的 Cname 加了UNIQUE约束给 Cno 加了PRIMARY KEY。两者都要求值唯一但有几个关键区别主键不允许为空唯一约束允许为空但只能有一个空值一张表只能有一个主键但可以有多个唯一约束。实验里检查唯一约束时尝试插入两个相同的课程名数据库会拒绝第二条。4.4 视图和表的区别视图看起来像表查起来也像表但它不存数据。你往视图里插数据实际上是在往底层表里插。如果视图的定义里包含聚合函数或者多表连接你可能根本没法往里插数据。实验里创建的Student_VIEW是一个简单的单表视图这种视图通常可以更新但S_G视图包含GROUP BY这种视图就不能直接更新。4.5 聚簇索引和非聚簇索引的差别实验里给 SC 表建了聚簇索引给 Course 表建了非聚簇索引。聚簇索引决定了数据在磁盘上的物理顺序一张表只能有一个聚簇索引。非聚簇索引则是独立于数据存储的目录结构一张表可以有多个。打个比方聚簇索引像是把书按章节顺序装订好非聚簇索引像是另外做了一份索引卡片放在旁边。5. 什么时候该用这些知识从实验报告到真实场景5.1 实验里的操作对应哪些实际工作这份实验报告虽然是一份课程作业但它覆盖的操作在真实工作中每天都在发生。建表对应的是系统设计阶段的数据库建模插入数据对应的是业务系统运行时的数据写入查询对应的是报表、搜索、数据分析约束对应的是数据质量保障索引对应的是性能优化。举个例子某公司的订单系统需要记录用户、商品、订单三张表。用户表的主键是用户 ID商品表的主键是商品 ID订单表用复合主键(用户ID, 商品ID, 下单时间)来保证同一用户在同一时间不会重复下单。这些设计思路跟实验里 Student、Course、SC 三张表的关系是一模一样的。5.2 什么时候该加索引什么时候不该加索引能加快查询速度但不是越多越好。实验里给 Cname 建了索引因为经常需要按课程名查询。但如果一张表经常被插入和更新索引反而会拖慢速度因为每次写数据都要同时更新索引。一般来说经常出现在 WHERE 条件、JOIN 条件、ORDER BY 里的字段适合加索引频繁更新的字段、数据量很小的表、区分度很低的字段比如性别只有男女两种值不适合加索引。5.3 约束该加多少实验里给 Ssex 加了 CHECK 约束给 Grade 加了范围约束给 Sno 和 Cno 加了外键约束。这些约束在真实系统里同样重要。但约束也不是越多越好。过多的约束会让数据插入变得困难尤其是在批量导入数据的场景下。一个常见的做法是核心业务字段加约束辅助字段放宽限制数据导入时先禁用约束导入完成后再启用。5.4 一个具体的判断例子假设你接手了一个学生管理系统需要查“选修了数据库系统原理且成绩在 90 分以上的学生姓名”。你可以用嵌套查询SELECT Sname FROM Student WHERE Sno IN ( SELECT Sno FROM SC WHERE Cno ( SELECT Cno FROM Course WHERE Cname 数据库系统原理 ) AND Grade 90 );也可以用连接查询SELECT Student.Sname FROM Student JOIN SC ON Student.Sno SC.Sno JOIN Course ON SC.Cno Course.Cno WHERE Course.Cname 数据库系统原理 AND SC.Grade 90;两种写法结果一样但连接查询通常更容易读懂而且在数据量大时性能往往更好。嵌套查询适合逻辑层次清晰的场景连接查询适合多表关联的场景。选择哪种取决于你的数据规模和可读性需求。提示在实际工作中写完查询后先用EXPLAIN看一下执行计划了解数据库是怎么执行这条语句的。这比凭感觉猜性能要靠谱得多。5.5 我踩过的那些坑刚开始学数据库的时候我总觉得 SQL 写出来能跑就行。直到有一次我在一个测试环境里写了一条UPDATE Student SET SageSage1忘了加 WHERE结果整张表的年龄全加了一岁。虽然数据可以恢复但那次之后我养成了一个习惯每次写 UPDATE 和 DELETE先写 WHERE 条件确认无误后再补前面的部分。还有一次我用 NULL去查空值查了半天没结果后来才知道要用IS NULL。这些血泪经验实验报告里不会写但每一个用过数据库的人都会遇到。从那以后我每次建表都会先想清楚主键是什么、哪些字段不能为空、哪些字段需要加约束。这些看似琐碎的细节在系统上线后就是数据质量的保障。希望这些内容能帮到你让你在下次面对数据库实验或者真实项目时少走一点弯路。本文还有配套的精品资源点击获取