北理工数据库上机实验包:SQL脚本与Node实战全解析
简介这份资源是北京理工大学计算机学院“数据库原理与设计”课程的上机实验资料包面向计算机科学与技术专业学生及需要巩固数据库实践能力的学习者。内容围绕数据库系统原理、关系模型、SQL语言、规范化设计、索引与查询优化等核心知识点展开帮助读者把课堂理论落到实际操作中。压缩包共12个文件约4.69MB以4个SQL脚本、3个JavaScript文件、2个JSON配置、1份PDF与1份Word实验报告及1个Markdown说明为主覆盖建库建表、数据查询与更新、嵌入式SQL、数据清理等实验环节。已有168人学习下载。读者可借助其中的实验报告、脚本与说明文档理解事务处理、并发控制、备份恢复等深层问题并参考报告结构完成实验总结与问题分析适合作为课程实验对照与查漏补缺的实践材料。1. 北理工数据库上机实验包一份能直接跑通的 SQL 训练场如果你正在学数据库或者要带数据库实验课大概率会遇到一个尴尬理论都懂但真给你一个空库让你从建表、插数据、写查询到做事务控制手会生。北理工计算机学院“数据库原理与设计”这门课的上机实验包恰好就是解决这个问题的。它把课程里从基础 DDL 到嵌入式 SQL 的完整链路拆成了 4.1、4.6、7 等多个编号的 SQL 脚本外加insert.js、embededSQL.js、truncateAndDelete.js三个 Node 脚本还有一份实验报告文档。适合谁正在修这门课要交实验报告的学生、想拿一套现成 SQL 案例练手的自学者以及需要给学生准备实验素材的助教。它不是视频课是一堆能直接导入数据库执行的脚本和代码。2. 拆包看结构每个文件对应哪个实验环节2.1 文件清单与实验阶段映射拿到sjkylysj-main这个目录后先别急着导入。我一般会先扫一遍文件搞清楚每个脚本对应课程里的哪个知识点。这个包的文件命名很直白数字编号基本对应实验章节。文件类型对应实验内容3.sqlSQL 脚本基础建表与约束定义4.1.sqlSQL 脚本单表查询与条件过滤4.6.sqlSQL 脚本多表连接与子查询7.sqlSQL 脚本视图、索引或事务控制insert.jsNode 脚本批量数据插入embededSQL.jsNode 脚本嵌入式 SQL 调用truncateAndDelete.jsNode 脚本删除操作对比实验package.json配置文件Node 依赖声明数据库上机实验报告.pdf/docx文档实验过程记录与结论这个结构说明它不是随便丢几个 SQL 文件而是按实验顺序组织的。3.sql 通常是第一道上机题建库建表4.x 系列是查询实验7.sql 偏向高级特性。三个 JS 文件则是把 SQL 嵌入到应用层的练习对应课程里“嵌入式 SQL”那一节。2.2 环境准备数据库选型和 Node 依赖课程原文没指定 DBMS但国内高校数据库实验最常用的是 MySQL 和 SQL Server。从脚本里如果出现AUTO_INCREMENT或LIMIT那就是 MySQL 语法如果出现IDENTITY或TOP就是 SQL Server。我建议先打开 3.sql 看几行确认方言再选环境。Node 脚本这边先看package.json里声明了什么依赖。常见的是mysql或mysql2包。操作步骤# 进入项目目录 cd sjkylysj-main # 安装依赖package-lock.json 已经锁了版本 npm install # 查看 package.json 确认入口和依赖 cat package.jsonnpm install会依据package-lock.json还原依赖树避免版本漂移。如果安装报错先检查 Node 版本mysql2一般要求 Node 14 以上。装完后不要急着跑 JS先把 SQL 脚本在数据库里执行一遍确保库表存在否则 JS 连上去也是空跑。提示如果 package.json 里没有 start 脚本直接node insert.js即可但前提是脚本里的连接配置已经改成你本地的地址和密码。3. SQL 脚本执行从建表到查询的完整链路3.1 建表脚本 3.sql 的执行与参数检查3.sql 是整个实验的地基。它里面通常包含CREATE DATABASE、USE、CREATE TABLE以及主外键约束。执行前先通读一遍重点看三处字符集、存储引擎、外键依赖顺序。-- 典型建表片段实际以 3.sql 为准 CREATE DATABASE IF NOT EXISTS lab_db DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_general_ci; USE lab_db; CREATE TABLE student ( sno CHAR(8) PRIMARY KEY, sname VARCHAR(20) NOT NULL, sage INT CHECK (sage BETWEEN 16 AND 40), sdept VARCHAR(30) ) ENGINEInnoDB;utf8mb4是为了支持中文姓名和生僻字InnoDB是事务和外键的前提。如果脚本里写的是MyISAM外键约束会被静默忽略后面做连接查询时数据对不上这就是玄学问题的根源。执行方式mysql -u root -p 3.sql或者进 MySQL 后用source命令。执行完用SHOW TABLES;确认表都建出来了。如果报 “Cannot add foreign key constraint”先检查被引用表是否已经创建以及字段类型是否完全一致——CHAR(8)和VARCHAR(8)在外键里不兼容。3.2 查询脚本 4.1 与 4.6 的递进关系4.1.sql 练的是单表条件查询4.6.sql 升级到多表连接和子查询。这两个脚本建议按顺序执行因为 4.6 依赖 4.1 里插入的数据。执行前先确认 insert.js 已经跑过或者脚本里自带了 INSERT 语句。-- 4.1 典型单表查询 SELECT sno, sname FROM student WHERE sdept 计算机学院; -- 4.6 典型多表连接 SELECT s.sname, c.cname, sc.grade FROM student s JOIN sc ON s.sno sc.sno JOIN course c ON sc.cno c.cno WHERE sc.grade 80;参数上要注意的是4.6 里的连接条件字段必须有索引否则数据量一大就变成慢 SQL。实验数据量小感觉不出来但这是养成习惯的地方。如果 4.6 执行报 “Unknown column”多半是 4.1 里的表名或字段名和 4.6 不一致以 3.sql 的定义为准去核对。3.3 7.sql 里的高级特性视图、索引或事务7.sql 编号靠后通常对应课程后半段的高级内容。打开看如果出现CREATE VIEW那就是视图实验出现CREATE INDEX是索引与查询优化出现START TRANSACTION和COMMIT就是事务控制。-- 事务控制示例 START TRANSACTION; UPDATE account SET balance balance - 100 WHERE id 1; UPDATE account SET balance balance 100 WHERE id 2; COMMIT;事务实验的关键是验证原子性故意在第二个 UPDATE 后加一句会报错的语句看第一个 UPDATE 是否回滚。如果没回滚检查表引擎是不是 InnoDB。这个脚本里的参数主要是隔离级别可以在事务前加SET TRANSACTION ISOLATION LEVEL READ COMMITTED;来观察不同级别下的并发行为。4. Node 脚本实战insert、embededSQL 与删除操作4.1 insert.js 批量插入与连接配置insert.js 的作用是往已经建好的表里灌数据。它一般用mysql2的createConnection或连接池。跑之前必须改连接配置否则连的是作者本地的库。// insert.js 关键片段 const mysql require(mysql2); const conn mysql.createConnection({ host: localhost, // 改成你的数据库地址 user: root, // 你的用户名 password: yourpass, // 你的密码 database: lab_db // 和 3.sql 里建的库名一致 }); const students [ [20210001, 张三, 20, 计算机学院], [20210002, 李四, 21, 计算机学院] ]; conn.query( INSERT INTO student (sno, sname, sage, sdept) VALUES ?, [students], (err, results) { if (err) throw err; console.log(插入行数:, results.affectedRows); conn.end(); } );VALUES ?配合二维数组是 mysql2 的批量插入写法比循环单条插入快一个数量级。affectedRows用来验证实际插入条数。如果报 “ER_NO_SUCH_TABLE”说明 database 名写错或 3.sql 没执行。如果报 “ER_BAD_FIELD_ERROR”检查字段顺序和表定义是否一致。4.2 embededSQL.js 嵌入式 SQL 的调用方式embededSQL.js 对应课程里的嵌入式 SQL 实验。它演示的是在宿主语言里嵌入 SQL 语句通常包含游标或者预处理语句。和 insert.js 的区别在于它更强调 SQL 与程序逻辑的交互。// embededSQL.js 典型结构 const sql SELECT sno, sname FROM student WHERE sdept ?; conn.execute(sql, [计算机学院], (err, rows) { if (err) throw err; rows.forEach(row { console.log(${row.sno} - ${row.sname}); }); });execute和query的区别在于execute走预处理能防 SQL 注入这也是实验报告里可以写的对比点。参数用?占位数组按顺序传。如果查询结果为空但表里明明有数据检查字符集是不是utf8mb4以及传入的字符串有没有多余空格。4.3 truncateAndDelete.js 的删除行为对比这个脚本是整包里最有实验价值的一个。它对比TRUNCATE和DELETE的行为差异对应课程里数据更新那一章。// truncateAndDelete.js 核心逻辑 conn.query(DELETE FROM student WHERE sdept ?, [计算机学院], (err, r1) { console.log(DELETE 影响行数:, r1.affectedRows); }); conn.query(TRUNCATE TABLE student, (err, r2) { console.log(TRUNCATE 执行完毕); });DELETE可以带 WHERE 条件走事务日志可以回滚affectedRows反映删除条数。TRUNCATE清空整表不走事务不能回滚速度更快但危险。实验报告里可以记录两者的执行时间差异和自增 ID 的变化TRUNCATE会重置AUTO_INCREMENTDELETE不会。跑这个脚本前先备份数据不然清空了只能重新跑 insert.js。5. 避坑与排查跑这套实验包最容易翻车的五个点5.1 脚本编码导致中文乱码现象执行 3.sql 后表里的中文系名变成问号或乱码。原因脚本文件本身是 GBK 编码而数据库连接默认 utf8mb4。解决用file 3.sql查看编码如果是 ISO-8859 或 GBK用iconv -f GBK -t UTF-8 3.sql 3_utf8.sql转码后再执行或者在连接串里显式指定charset: utf8mb4。5.2 外键约束导致插入顺序报错现象insert.js 报 “Cannot add or update a child row”。原因先插了子表数据父表还没有对应记录。解决按 3.sql 里的建表顺序先插父表如 student、course再插子表如 sc。如果脚本里插入顺序反了手动调整或临时SET FOREIGN_KEY_CHECKS0;但实验报告里要说明这只是调试手段。5.3 Node 连接报 ECONNREFUSED现象node insert.js报 “connect ECONNREFUSED 127.0.0.1:3306”。原因数据库服务没启动或者端口不是 3306。解决先mysql -u root -p能登进去确认服务在跑然后检查脚本里的 host 和 port如果是 Docker 里的数据库host 要改成容器映射的地址。5.4 TRUNCATE 后自增 ID 重置导致关联断裂现象跑完 truncateAndDelete.js 后重新插入学生 ID 从 1 开始但之前关联的选课记录还引用旧 ID。原因TRUNCATE重置了AUTO_INCREMENT而关联表数据没清。解决要么同时清空所有关联表要么用DELETE代替TRUNCATE保留自增序列。实验里建议两种都跑一遍把差异写进报告。5.5 实验报告文档与脚本版本不一致现象照着 PDF 报告里的 SQL 写执行报错因为报告里的表结构和 3.sql 对不上。原因报告是往届版本脚本是更新过的。解决以sjkylysj-main里的 SQL 脚本为唯一事实来源报告只参考实验步骤和结论格式。如果报告里的字段名和脚本不同以脚本为准在报告里注明实际使用的结构。6. 进阶验证用事务和慢查询日志检验实验成果跑通所有脚本只是及格线。要真正把这套实验包的价值榨干我一般会做两件事一是用事务回滚验证数据一致性二是开慢查询日志看 4.6.sql 的执行计划。先做事务验证。在 7.sql 的基础上手动构造一个转账场景故意让第二步失败观察第一步是否回滚USE lab_db; START TRANSACTION; UPDATE account SET balance balance - 100 WHERE id 1; -- 下面这句故意引用不存在的表触发错误 UPDATE nonexist_table SET balance balance 100 WHERE id 2; ROLLBACK; SELECT * FROM account WHERE id 1;如果id1的余额没变说明事务原子性生效InnoDB 引擎工作正常。如果变了检查表是不是 MyISAM。这个验证比单纯跑脚本更有说服力实验报告里放上前后对比截图分数不会低。再看查询优化。4.6.sql 里的多表连接在实验数据量下可能几十毫秒就返回但你可以用EXPLAIN看它走了什么索引EXPLAIN SELECT s.sname, c.cname, sc.grade FROM student s JOIN sc ON s.sno sc.sno JOIN course c ON sc.cno c.cno WHERE sc.grade 80;重点看type列是不是ALL全表扫描key列是不是NULL。如果是说明连接字段没索引可以在sc.sno和sc.cno上建索引再对比。这个对比实验能直接对应课程里“查询优化”那一节比背概念强得多。还有一个容易忽略的点embededSQL.js里的预处理语句可以用EXPLAIN看它和普通query的执行计划差异。虽然 mysql2 的execute底层也是预处理但实验报告里可以记录query和execute在多次执行下的耗时差异作为嵌入式 SQL 性能分析的素材。最后说个血泪经验这套包里的 SQL 脚本编号不连续3、4.1、4.6、7中间缺的编号可能是选做实验或者被老师删了。不要以为是文件缺失按现有编号跑就行。另外package-lock.json里的依赖版本可能比较老npm install如果报 peer 依赖冲突用npm install --legacy-peer-deps绕过但要在报告里注明环境差异。从那以后我每次拿到这种课程实验包都先npm install再mysql 3.sql最后才碰 JS 脚本顺序反了就是给自己找麻烦。希望帮到你。本文还有配套的精品资源点击获取