资讯详情

资讯详情

数据库课后实验避坑指南:从环境配置到触发器,照做不翻车

简介这份数据库课后实验材料出自崔巍编著的教材配套练习面向高校数据库课程学习者目标是借助上机操作深入掌握结构化查询语言、关系模式设计与事务处理等核心内容。压缩包内共收录五个文件全部为结构化查询语言脚本整个压缩包仅五KB但实验点较为完整脚本以编号区分依次涉及建库建表、数据插入、多表连接、分组统计与筛选、事务提交与回滚等常见课堂练习。当前已有两百二十人学习浏览适合用于课后作业参考、实验报告撰写以及考前集中复习。通过亲手运行并修改脚本能够直观理解查询语句的执行结果体会范式设计对数据冗余的抑制作用同时认识事务与索引在数据操作中的实际作用从而快速掌握数据库核心概念积累一套可复用、可扩展、可直接迁移到后续实验或项目中的实战语句模板。1. 数据库课后实验崔巍编著为什么照着教材敲代码还会翻车很多人拿到《数据库课后实验崔巍编著》这本实验册第一反应是从第一章的 CREATE DATABASE 一路敲到最后一章的触发器。但真正让实验卡壳的往往不是 SQL 语法而是环境、权限、提交时机这些藏在每个实验背后的“隐形扣分项”。这本实验册的覆盖面很典型建库建表、增删改查、索引视图、存储过程与触发器、事务与安全性管理顺着它能完整走一遍 T-SQL 的开发闭环适合正在补作业的学生、要带新人跑数据库训练的一线工程师以及想用一套经典题目复习 SQL Server 的老手。下面按我平时带实验的顺序讲先搭环境再跑基础 SQL最后攻索引、存储过程和触发器附一份提交前的自查脚本。2. 建环境装好数据库不等于能交实验登录名与权限才是第一关实验册开头往往是“安装数据库管理系统”这一节很多人以为装完就能开跑结果卡在第一步连不上、没有登录名、默认库不对。这一章把环境层面的三个问题一次说清——选哪个数据库、服务怎么起、登录名怎么建。环境没铺平后面所有实验都会在同一个地方重复翻车。2.1 实验册的 SQL 是 T-SQL 方言先确认你的数据库给不给面子这本实验册的示例基本按 T-SQL 编写典型的配套环境是 SQL Server。有些同学图省事装了 MySQL跑第一个查询就报错最典型的是取前几行、日期函数、字符串拼接这些写法对不上。两种数据库的差异比想象中大得多不是改一两个关键字就能跑通的。功能实验册常用写法T-SQLMySQL 等价写法取前 N 行SELECT TOP 5 ...SELECT ... LIMIT 5当前时间GETDATE()NOW()空值替换ISNULL(列, 0)IFNULL(列, 0)自增列IDENTITY(1,1)AUTO_INCREMENT字符串拼接用 连接CONCAT()删表前判断IF OBJECT_ID(...) IS NOT NULL DROP TABLEDROP TABLE IF EXISTS上表不是鼓励你去做语法翻译恰恰相反如果你正跟着这本实验册做课后实验我建议直接用 SQL Server别在 MySQL 上硬扛。事务隔离级别、触发器语法、系统视图名称两边差异很大实验册里关于权限和备份的章节在 MySQL 里甚至找不到对应操作。用错数据库相当于在实验开始前就给自己挖了两倍的坑。2.2 装好 SQL Server 后先做三件事服务、协议、登录名装完 SQL Server 第一件事不是打开图形工具建表而是确认服务确实在跑。常见默认实例的服务名是 MSSQLSERVER命名实例形如 MSSQL$实例名。用管理员身份打开命令提示符执行:: 查看 SQL Server 默认实例服务状态 sc query MSSQLSERVER :: 如果状态不是 RUNNING启动服务 net start MSSQLSERVERsc query 的输出里看 STATE 这一行是 RUNNING 才能继续。服务没起来时图形工具会报“无法连接到 localhost”很多人以为是自己装坏了其实只是服务停了。在实验机上尤其常见——上次关机前没正常停止服务或者系统更新后服务启动类型被改成了手动。服务启动后强烈建议建一个自己的登录名不要全程用 sa 裸奔。实验册里的权限实验要以普通用户的视角去做不然 GRANT 和 REVOKE 做出来全是“假动作”。在查询窗口里执行-- 在实例层创建登录名指定默认数据库 CREATE LOGIN lab_user WITH PASSWORD Lab12345, DEFAULT_DATABASE labdb; -- 切换到目标数据库后在数据库层创建同名用户 USE labdb; CREATE USER lab_user FOR LOGIN lab_user;这里有个初学者最容易漏的点CREATE LOGIN 建在实例层CREATE USER 建在数据库层两层都要有登录名才能访问库。如果漏了 USE labdb会报“当前上下文中不存在名为 lab_user 的用户”。密码复杂度可以按本机策略调低但建议保留一个固定密码用于整个实验周期别每节课建一个。2.3 给实验册建一个专用数据库命名规则与文件位置建库这一步看似简单但文件位置和增长参数会影响你后面所有实验。不要用默认库也不要建在 C 盘系统盘上。我一般会在数据盘单独建一个 LabData 目录库名用 labdb这样实验做完备份和清理都方便CREATE DATABASE labdb ON PRIMARY ( NAME labdb, FILENAME ND:\LabData\labdb.mdf, SIZE 16MB, MAXSIZE 512MB, FILEGROWTH 16MB ) LOG ON ( NAME labdb_log, FILENAME ND:\LabData\labdb_log.ldf, SIZE 8MB, MAXSIZE 128MB, FILEGROWTH 8MB );FILENAME 里的路径要真实存在否则建库报错N 前缀是为了让 SQL Server 正确识别中文路径。SIZE 是初始大小FILEGROWTH 是每次自动增长的步长MAXSIZE 给个上限防止日志文件无限膨胀。实验数据量很小建完后建议把恢复模式改成 SIMPLE省掉不必要的日志开销ALTER DATABASE labdb SET RECOVERY SIMPLE;注意这是实验环境才这么干。生产库开 SIMPLE 模式会丢掉时间点恢复能力这个习惯不要带出去。建好库、建好登录名、确认服务能起环境这关就算过了。3. 建库建表与增删改查把教材实验册的 SQL 跑道先铺平环境准备好后进入实验册正文最前面的核心内容建表、插数据、查数据。这章看起来基础但实验报告里的扣分点大多集中在这里——字段类型选错、约束没建全、UPDATE 忘了带 WHERE。这三个小节把最经典的“学生-课程-选课”三张表从零建一遍。3.1 建表实验主键、外键、默认值、CHECK 约束一次写全建表实验的核心不是把字段敲出来而是把约束一次写全。以数据库教材里最经典的学生选课结构为例这里有三个典型的坑学号用 CHAR 还是 VARCHAR、成绩用什么精度、外键怎么定义。下面这段是完整可跑的建表脚本USE labdb; -- 学生表学号定长字符主键姓名非空性别带默认值和 CHECK CREATE TABLE student ( sno CHAR(9) PRIMARY KEY, sname VARCHAR(20) NOT NULL, ssex CHAR(2) DEFAULT 男 CHECK (ssex IN (男, 女)), sage SMALLINT CHECK (sage 16 AND sage 30), sdept VARCHAR(30) ); -- 课程表课程号主键先修课号允许为空 CREATE TABLE course ( cno CHAR(4) PRIMARY KEY, cname VARCHAR(40) NOT NULL, cpno CHAR(4) NULL, ccredit SMALLINT CHECK (ccredit 0) ); -- 选课表联合主键两个外键分别引用上面两张表 CREATE TABLE sc ( sno CHAR(9) REFERENCES student(sno), cno CHAR(4) REFERENCES course(cno), grade NUMERIC(5, 2) CHECK (grade 0 AND grade 100), PRIMARY KEY (sno, cno) );学号用 CHAR(9) 是因为学号是定长编码前 4 位年级后 5 位序号用 VARCHAR 也不会省空间CHAR 还避免了末尾空格隐患。sage 用 SMALLINT 而不是 INT范围足够且省空间。grade 用 NUMERIC(5,2) 而不是 FLOAT——成绩要精确比较浮点数的二进制表示会让你 59.5 分显示成 59.49999...这种“玄学”问题在实验报告里非常难看。外键有个容易被忽略的细节sc 表的两个外键字段类型必须和主表完全一致。student.sno 是 CHAR(9)sc.sno 就必须是 CHAR(9)写成 VARCHAR(9) 虽然能建但查询时隐式转换会让索引失效。以后你在执行计划里看到 Index Scan 而不是 Index Seek先查这一处。3.2 数据更新实验INSERT 的三种写法与 UPDATE 的“忘了 WHERE”事故插入数据的实验看着简单但实验册里的课后题经常要求“用多种方式插入”。三种写法各有用处全列插入最省事但最脆指定列插入灵活多行插入适合初始化实验数据。看这段-- 方式一按表定义顺序全列插入少一个字段就报错 INSERT INTO student VALUES (20230001, 张三, 男, 20, 计算机); -- 方式二指定列名没给的列用默认值或 NULL INSERT INTO student (sno, sname, ssex, sage) VALUES (20230002, 李四, 女, 21); -- 方式三一次插多行VALUES 后面跟多个括号 INSERT INTO student (sno, sname, ssex, sage, sdept) VALUES (20230003, 王五, 男, 19, 软件工程), (20230004, 赵六, 男, 20, 计算机);方式二里 sdept 没给会落成 NULL。如果你实验报告里要求“每个字段都有值”这种方式就不适用。方式三是初始化实验数据最快的写法实验册要求插入 10 条以上记录时用它一次性搞定。UPDATE 的事故现场几乎都是同一个忘了 WHERE。下面这个误操作是每个数据库人都经历过的-- 危险写法没带 WHERE把全表成绩清零 UPDATE sc SET grade 0; -- 正确写法先 SELECT 确认影响行再执行 UPDATE SELECT * FROM sc WHERE cno C001; UPDATE sc SET grade grade * 1.1 WHERE cno C001;如果误操作已经执行了别慌。前提是你提前开了事务后悔药就在回滚里BEGIN TRANSACTION; UPDATE sc SET grade 0; -- 发现不对回滚 ROLLBACK;唯一能救你的就是事务。没开事务直接执行 UPDATE 且没有备份基本只能靠恢复前的备份文件。所以做数据更新实验时我要求每条 UPDATE 前先跑 SELECT确认 WHERE 条件选中的是自己要改的行再用 UPDATE 改。这个习惯成本极低收益极高。3.3 查询实验单表、多表 JOIN 与 GROUP BY 的常见扣分点查询是实验册里篇幅最大的部分扣分点也最密集。三个最容易丢分的地方JOIN 条件写成 WHERE 笛卡尔积、GROUP BY 的列没写全、COUNT(列) 和 COUNT(*) 用错。看这个覆盖多表查询和分组的完整例子-- 查询每个系学生的选课平均成绩只列出平均分及格的结果 SELECT s.sdept, AVG(sc.grade) AS avg_grade, COUNT(DISTINCT sc.sno) AS stu_cnt FROM student s JOIN sc ON s.sno sc.sno GROUP BY s.sdept HAVING AVG(sc.grade) 60 ORDER BY avg_grade DESC;GROUP BY 只写了 s.sdept所以 SELECT 列表里只能出现 s.sdept 和聚合函数。想输出 sname 或者 s.ssex 就必须把它们也加进 GROUP BY这是 SQL Server 的硬性规则不是可选项。COUNT(DISTINCT sc.sno) 统计的是选课人数而不是选课记录数——这两个值在一个人选多门课的时候差很多实验报告里用错会被直接扣分。HAVING 和 WHERE 的区别也是一个高频考点WHERE 过滤的是 JOIN 之前的行HAVING 过滤的是 GROUP BY 之后的分组。想筛选“平均分大于 60 的系”条件写 HAVING 里想筛选“计算机系的学生”条件写 WHERE 里等聚合后再过滤会漏掉没选课的人。查完数据看不到预期结果时别急着改 SQL先把中间结果跑一遍——去掉 GROUP BY 看明细再手动算一组数据核对聚合结果。数据库查询是一个黑匣子但拆开它的办法永远是分步验证。4. 索引、视图、存储过程与触发器实验册里最容易被扣分的四座山基础 SQL 过了以后实验册进入进阶部分索引、视图、存储过程和触发器。这四块是实验报告里“拉开差距”的内容前面抄代码能拿分这里抄代码只能拿基础分。关键在于理解每个对象背后的机制——索引什么时候生效、视图能不能更新、触发器为什么会导致数据“消失”。4.1 索引实验从执行计划看索引到底用没用到索引实验里最常见的写法是建完索引就交差但实验报告的老师更想看的是“索引前后查询性能的变化”。建索引本身很简单-- 在选课表的学号列建普通索引加速 学生-选课 的 JOIN CREATE INDEX idx_sc_sno ON sc(sno); -- 在课程名列建唯一索引防止课程重名 CREATE UNIQUE INDEX idx_course_cname ON course(cname);关键在于验证索引有没有被用上。SQL Server 里最直接的验证方式是打开执行计划工具栏里“包含实际执行计划”按钮或者用下面这两条命令看硬指标SET STATISTICS IO ON; SET STATISTICS TIME ON; SELECT s.sname, c.cname, sc.grade FROM sc JOIN student s ON sc.sno s.sno JOIN course c ON sc.cno c.cno WHERE s.sdept 计算机;跑完以后看消息选项卡里的“逻辑读取次数”和“CPU 时间”。同一句查询建索引前后逻辑读从几十降到几个说明索引生效了数值几乎没变说明查询压根没走索引——常见原因是 WHERE 条件里的列没建索引或者 JOIN 条件上发生了隐式类型转换。这里有个实验册里不会明说的边界索引不是建得越多越好。每个表加索引都要付出写入代价实验册的课后数据量太小往往建了索引也看不出性能差异这时候就把执行计划的截图贴进报告对比 Scan 和 Seek 的不同。索引实验的分数不在“能不能建”在“能不能解释清楚”。4.2 视图与存储过程把重复查询封装成实验册里的“黑匣子”视图的本质是一个保存的查询存储过程是保存的批处理。实验册把这俩放在一起讲是因为它们的共同点是“封装”——把一段复杂的 SQL 存起来下次直接用名字调用。下面是这个实验最常见的两个对象-- 视图每个学生的选课平均成绩 CREATE VIEW v_sc_avg AS SELECT sno, AVG(grade) AS avg_grade FROM sc GROUP BY sno; -- 存储过程根据学号查询成绩单 CREATE PROCEDURE usp_get_student_grade sno CHAR(9) AS BEGIN SELECT s.sname, c.cname, sc.grade FROM sc JOIN course c ON sc.cno c.cno JOIN student s ON sc.sno s.sno WHERE sc.sno sno; END;视图的坑在于“能不能更新”。v_sc_avg 用了 GROUP BY这种视图在 SQL Server 里默认不可更新对它执行 UPDATE 会报错。实验册里如果要求“通过视图插入数据”视图只能建立在单表基础上且不能带聚合和 DISTINCT。很多同学在这里报错后以为是视图写错了其实是视图类型不支持更新。存储过程的调用方式是 EXEC不是 SELECTEXEC usp_get_student_grade sno 20230001;参数 sno 是输入参数形如 开头。参数的类型和长度必须匹配写成 sno 20230001 是因为学号定长 CHAR(9)但参数声明时给了 CHAR(9)字符串可以自动匹配长度。存储过程的好处是可以把多步操作打包成一个逻辑单元实验报告里描述业务场景时比一段裸 SQL 清晰得多。4.3 触发器实验AFTER 与 INSTEAD OF 的适用边界触发器是实验册里最像“魔法”的部分——一个操作引发另一段 SQL 自动执行。但魔法有魔法的代价触发器里出了问题你根本不知道数据是被谁改的。先看最常见的 AFTER 触发器-- 在选课表上建触发器插入负数成绩直接回滚 CREATE TRIGGER trg_sc_insert ON sc AFTER INSERT AS BEGIN IF EXISTS (SELECT 1 FROM inserted WHERE grade 0) BEGIN RAISERROR(成绩不能为负数, 16, 1); ROLLBACK TRANSACTION; END END;AFTER 触发器在操作完成之后触发inserted 表里装的是新插入的行。这段触发器检查新行里有没有负数成绩有就报错并回滚——插入的语句表面上执行了但实际没生效这就是触发器让数据“神秘消失”的原因之一。反过来INSTEAD OF 触发器是在操作发生前拦截替代原操作执行。两者的边界是AFTER 用于审计和数据校验INSTEAD OF 用于视图插入、复杂逻辑的替代处理。维度AFTER 触发器INSTEAD OF 触发器触发时机原操作成功后原操作被替代不执行原操作适用场景校验、审计日志、同步更新视图插入、阻止非法操作inserted/deleted 表有有典型误用触发器里再次触发同表触发器以为原操作还会执行触发器实验的另一个边界是递归和嵌套。SQL Server 的嵌套层数上限是 32 层超过会报错并回滚整个事务。实验册里如果让你在 student 表上写 UPDATE 触发器触发器里又 UPDATE 了 student 表就会自己触发自己。解决办法是加条件判断或者临时禁用触发器-- 禁用触发器避免递归 DISABLE TRIGGER trg_sc_insert ON sc; -- 用完再启用 ENABLE TRIGGER trg_sc_insert ON sc;我见过最惨的翻车现场是某同学写了一个 AFTER INSERT 触发器里面又往同一张表 INSERT触发递归直到报错。排错花了整整一个下午最后发现触发器里缺一个 IF 条件判断。写触发器之前先问自己一句这段自动逻辑会不会导致原表再次被修改5. 数据库课后实验避坑指南5 个高频翻车点的现象、原因与解决前面几章讲的是怎么做这一章讲做的时候最容易踩的坑。每一条都是实际带实验时反复出现的问题按“现象 → 原因 → 解决”的顺序写清楚遇到同款问题时可以直接照方抓药。5.1 连不上本地数据库服务没启动与协议未启用现象SQL Server 图形工具登录时报“无法连接到 localhost”错误码通常是 26 或 40翻译成人话就是“网络上的计算机或服务不可见”。原因最常见是服务根本没启动其次是 SQL Server 配置管理器里的 TCP/IP 协议被禁用。默认安装时本机连接走 Shared Memory 协议够用但某些实验要求用 TCP/IP 连接协议没开就连不上。还有一种是装了 SQL Server Express 版默认实例名是 SQLEXPRESS连接时写 localhost 找不到要写 localhost\SQLEXPRESS。解决先跑 sc query MSSQLSERVER 或 sc query MSSQL$SQLEXPRESS 确认服务状态停止就 net start然后在 SQL Server 配置管理器里把“MSSQLSERVER 的协议”下的 TCP/IP 启用重启服务。用命令行快速测试端口telnet localhost 1433telnet 能连通说明服务和协议都正常还连不上就是登录名或防火墙的问题按 2.2 节检查登录名配置。5.2 中文乱码与排序规则冲突现象插入的中文数据变成问号或者查询报“无法解决排序规则冲突”。最常见的是 INSERT 语句里直接写中文查出来是 ???但别人插入的又是正常中文。原因数据库的排序规则不是中文相关或者客户端连接和服务器代码页不匹配。排序规则决定字符串如何比较和存储Collation 不对时中文会直接落成乱码。SQL Server 安装时如果选了英文区域默认排序规则可能是 SQL_Latin1_General_CP1_CI_AS这种规则对中文字符支持不完整。解决建库时显式指定中文排序规则这是一劳永逸的写法CREATE DATABASE labdb COLLATE Chinese_PRC_CI_AS;如果数据库已经建好且数据还没写可以整库改排序规则再重建表。如果只是个别查询里比较字符串用 COLLATE 临时指定SELECT * FROM student WHERE sname COLLATE Chinese_PRC_CI_AS N张三;这里还有一个易忽略的细节字符串前面加 N 前缀N张三 按 Unicode 处理不加 N 的先按代码页转换再比较。写中文条件时养成加 N 前缀的习惯能避开一半乱码问题。5.3 权限不足存储过程能创建却执行不了现象用 lab_user 登录后能创建存储过程但一执行就报“对象 usp_get_student_grade 的 EXECUTE 权限被拒绝”或者直接看不到这个存储过程。原因CREATE PROCEDURE 权限和 EXECUTE 权限是两码事。在 SQL Server 里存储过程的属主如果没有显式授权普通用户默认没有执行权限。更隐蔽的是所有权链问题——过程属于 lab_user但过程里访问的 student 表属于 dbo跨越属主之后存储过程里表的 SELECT 权限不会自动继承。解决显式授权是最直接的做法GRANT EXECUTE ON usp_get_student_grade TO lab_user; GRANT SELECT ON student TO lab_user; GRANT SELECT ON sc TO lab_user; GRANT SELECT ON course TO lab_user;提一个排查顺序先确认当前登录名是哪个SELECT SUSER_SNAME()再确认存储过程的属主sys.procedures 里的 principal_id最后确认表和过程的属主是不是同一个。三者一致时权限最顺不一致时老老实实逐个授权不要试图通过改属主来绕过。5.4 数据“没改”事务忘了 COMMIT 与触发器里的 ROLLBACK现象执行了 INSERT 或 UPDATESELECT 查不到变化或者当时能看到数据重启数据库后没了。原因两个典型。第一显式开启了事务但没 COMMIT连接退出时事务被回滚第二触发器里带了 ROLLBACK TRANSACTION数据看着插进去了实际被启动器回滚了。第二种特别坑因为 INSERT 语句本身没报错消息里只有一行“事务在触发器中结束”很多人扫一眼就略过了。解决养成“事务成对写”的习惯。BEGIN TRANSACTION 后面紧跟 TRY-CATCH成功 COMMIT失败 ROLLBACK不要依赖可视化工具的自动提交。怀疑触发器回滚时检查 XACT_STATE()-- 当前连接是否有未提交事务 SELECT XACT_STATE() AS state; -- 1 有活动事务0 无事务-1 有不可提交的事务返回值 -1 说明当前事务已经被标记为不可提交这时 COMMIT 会报错必须 ROLLBACK。遇到触发器导致的问题先把触发器临时禁用排除干扰项再定位逻辑。5.5 触发器死循环与嵌套层数超限现象执行一条 UPDATE报错“最大存储过程嵌套层数已超出32”或者更新一张表后其他表的数据也发生了莫名其妙的联动变化。原因触发器里有语句再次更新了本表数据或者触发器链太长。比如 student 表上的 UPDATE 触发器里又写了一句 UPDATE student更新动作再次触发同一触发器形成无限递归。当嵌套层数达到 32 层时SQL Server 终止执行并回滚。解决在触发器开头加条件判断避免无意义的重复触发CREATE TRIGGER trg_student_update ON student AFTER UPDATE AS BEGIN -- 如果只有 sage 被更新不需要额外处理 IF NOT UPDATE(sname) RETURN; -- 业务逻辑从这里开始 END;IF UPDATE(列名) 判断的是该列是否出现在 UPDATE 语句中不是值是否变化。如果实验册要求“每次更新姓名时记录日志”在触发器里判断 UPDATE(sname)再执行日志表的写入而不是再次更新 student 表。触发器和递归的排查技巧把触发器逐个禁用找到是哪一个在捣乱DISABLE TRIGGER trg_student_update ON student; -- 重新执行原 UPDATE不再报错就锁定目标 ENABLE TRIGGER trg_student_update ON student;触发器这章的关键是克制——能不用触发器实现的逻辑优先用约束和存储过程实在要用一定要把触发条件写窄不让它轻易自我触发。6. 交实验前跑一遍自查脚本用一份 SQL 验证数据库实验完成度实验做完到提交之间我习惯固定跑一遍自查脚本。不是重新执行一遍所有实验而是用一个清单脚本检查关键对象是否存在、数据是否完整、约束是否生效。把下面这段存成 .sql 文件每次提交前执行一次USE labdb; -- 1. 核心表是否存在缺表的行会返回表名 SELECT checklist.tbl AS missing_table FROM (VALUES (student), (course), (sc)) AS checklist(tbl) LEFT JOIN sys.tables t ON t.name checklist.tbl WHERE t.name IS NULL; -- 2. 每张表是否已有实验数据 SELECT student AS tb, COUNT(*) AS row_cnt FROM student UNION ALL SELECT course, COUNT(*) FROM course UNION ALL SELECT sc, COUNT(*) FROM sc; -- 3. 外键是否生效插入不存在的学号应报错 BEGIN TRY INSERT INTO sc (sno, cno, grade) VALUES (99999999, C001, 60); SELECT fk_check AS result, FAIL AS status; END TRY BEGIN CATCH SELECT fk_check AS result, PASS AS status; END CATCH; -- 4. 存储过程和触发器是否存在 SELECT name, type_desc FROM sys.objects WHERE name IN (usp_get_student_grade, trg_sc_insert);第一段检查表是否齐全漏建的表会出现在结果里第二段看数据量空表一眼就能看出来第三段故意插入一条违反外键的数据如果返回 FAIL说明外键约束没建上第四段检查进阶对象是否创建成功。每一段脚本都只看一个维度跑完扫一眼结果就知道实验缺什么。这套脚本只能验证“对象存在和数据完整”验证不了“逻辑是否正确”。它给不了你满分但能挡住最低级的失误——我曾经有一次把外键漏了数据随便插都成功实验报告里还写了外键的分析提交前一晚跑脚本才发现外键根本没生效整段分析等于白写。后来就养成了提交前必跑脚本的习惯。你要做实验的话把它当成最后一道关配合自己实验报告里的重点结论再看一遍。希望帮到你。本文还有配套的精品资源点击获取
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →