简介这份数据库课程设计文档面向计算机科学与技术等专业的学生围绕汽车修理管理系统展开完整的数据库设计实践帮助读者将数据库原理落地到真实业务场景中。内容涵盖系统概述、需求分析、数据库逻辑设计、软件功能设计与界面设计等模块具体包括业务工作流图、数据流图、E-R图、数据字典与关系图并细化到汽车、修理工、零件、用户等实体的属性与关联以及客户管理、车辆管理、维修订单、配件库存和报表统计等功能设计。资源包共1个doc文件约771KB为可直接参考的课程设计报告文档目录结构清晰便于按章节查阅与借鉴。目前已有162人学习适合需要完成数据库课程设计、撰写设计报告或参考E-R建模与表结构设计思路的学生使用。1. 从一份 .doc 说起汽车修理管理系统到底交付了什么很多人拿到「数据库课程设计-汽车修理管理系统.doc」的第一反应是这不就是一份 Word 文档吗能跑吗我一开始也这么想直到把它从头到尾拆了一遍才发现这份文档的价值不在「能不能直接运行」而在于它把一个小型信息管理系统的完整设计链路走通了——从业务工作流图、数据流图到 E-R 图、数据字典、关系图再到功能模块划分和 ADO 访问方式的设计。它本质上是一份数据库课程设计的完整设计说明书配套的是 Access 数据库 Visual C 6.0 ADO 这套经典组合。它解决的问题很具体汽车修理厂从修车登记、派工、零件领用、零件入库、开发票到工资月报、零件订货计划这一整条业务链怎么用关系型数据库把它建模出来。适合谁正在做数据库课程设计的学生、需要一份完整 E-R 图和数据字典参考的初学者以及想拿一个真实业务场景练手 SQL 建表和增删改查的从业者。文档里 12 张业务表、7 张核心数据字典表、明确的实体关系和主外键约束这些才是真正能抄作业的部分。2. 数据字典拆解12 张业务表怎么落到 SQL 建表这份文档最硬的部分是第 3 章的数据字典它把系统用户、汽车登记单、汽车修理单、零件领用单、零件入库单、修车发票、修理工名册、零件计划与库存这 8 类核心表全部列了出来字段名、数据类型、可否为空、权限说明一应俱全。但文档给的是表格不是可执行的 SQL所以第一步就是把这些表格翻译成建表语句。2.1 从数据字典到 CREATE TABLE 的映射规则先看文档里几个关键字段的类型约定UserID varchar not null 主键、RepairDate Date null、RepaireHourNum Float not null、PartNumber Int not null。这里有个容易翻车的地方——文档写的是varchar和Date但没写长度。Access 里 varchar 默认可以不给长度但如果你要迁到 MySQL 或 SQL Servervarchar必须指定长度否则建表直接报错。我一般会按业务含义估车牌号varchar(20)、姓名varchar(50)、身份证号varchar(18)、电话varchar(20)、地址varchar(200)。另一个坑是主键类型。文档里所有主键都是varchar包括OrderID修理单编号、PartID零件号、InvoiceID发票编号。用字符串做主键在课程设计里没问题但实际业务中如果编号是自增的用INT AUTO_INCREMENT更合适。这里我建议忠于文档保持varchar主键因为文档的业务逻辑里编号是人工编排的比如修理单编号可能带日期前缀改成自增反而对不上。2.2 核心建表语句与约束设置下面是我按文档数据字典整理出的建表 SQL以 MySQL 为例字段名和类型严格对照文档只补了必要的长度-- 系统用户信息表 CREATE TABLE sys_user ( UserID VARCHAR(20) NOT NULL PRIMARY KEY COMMENT 用户编号, UserName VARCHAR(50) NULL COMMENT 用户名, UserType INT NULL COMMENT 用户类型编码, UserPassword VARCHAR(50) NOT NULL COMMENT 用户密码 ); -- 汽车登记单信息表 CREATE TABLE car_register ( CarSerialNumber VARCHAR(20) NOT NULL PRIMARY KEY COMMENT 车牌号, CarStyle VARCHAR(50) NULL COMMENT 型号, Manufacture VARCHAR(100) NULL COMMENT 厂商, Owner VARCHAR(50) NOT NULL COMMENT 车主名, Telephone VARCHAR(20) NOT NULL COMMENT 电话, Address VARCHAR(200) NULL COMMENT 地址 ); -- 汽车修理单信息表 CREATE TABLE repair_order ( OrderID VARCHAR(20) NOT NULL PRIMARY KEY COMMENT 修理单编号, CarSerialNumber VARCHAR(20) NOT NULL COMMENT 汽车牌号, RepairPeopleId VARCHAR(20) NOT NULL COMMENT 修理工工号, RepairProject VARCHAR(200) NULL COMMENT 修理项目, RepairDate DATE NULL COMMENT 送修日期, AssignPeopleId VARCHAR(20) NULL COMMENT 派工员工号, FinishDate DATE NULL COMMENT 完工日期, RepaireHourNum FLOAT NOT NULL COMMENT 修理小时数, CONSTRAINT fk_order_car FOREIGN KEY (CarSerialNumber) REFERENCES car_register(CarSerialNumber), CONSTRAINT fk_order_man FOREIGN KEY (RepairPeopleId) REFERENCES repair_people(RepairPeopleId) ); -- 修理工名册表 CREATE TABLE repair_people ( RepairPeopleId VARCHAR(20) NOT NULL PRIMARY KEY COMMENT 工号, IdentifyNbr VARCHAR(18) NULL COMMENT 身份证号, RepairPeopleName VARCHAR(50) NOT NULL COMMENT 姓名, SalaryPerHour FLOAT NOT NULL COMMENT 小时工资, BirthDate DATE NOT NULL COMMENT 出生日期, WorkDate DATE NOT NULL COMMENT 进厂日期, Address VARCHAR(200) NOT NULL COMMENT 地址, Telephone VARCHAR(20) NULL COMMENT 电话 );逻辑说明repair_order表里有两个外键分别指向car_register和repair_people这对应文档 E-R 图里「一辆汽车可有多次维修记录」和「一个修理工可参与多个修理单」的一对多关系。注意建表顺序——repair_order依赖car_register和repair_people所以必须先建后两张表否则外键约束会报错。这是新手最容易踩的顺序坑。参数说明FLOAT用于RepaireHourNum和SalaryPerHour因为工时可能是 1.5 小时这种小数DATE用于所有日期字段不要用DATETIME文档里没有时间精度要求。NOT NULL的字段严格按文档来比如Owner、Telephone在汽车登记表里是必填的建表时不要漏。2.3 零件库存与订货计划的表设计零件相关的表是这份设计里业务逻辑最复杂的部分。文档里零件计划与库存信息表同时承担了库存和订货两个职责字段包括PartPrice价格、PartCost成本、OrderNumber订货量、TotalCost总计、StockNumber库存量、LowestStockNumber最低库存量。这里有个设计上的取舍价格和成本分开存是因为零件费按价格算、采购成本按成本算两者不能混。-- 零件计划与库存信息表 CREATE TABLE part_stock ( PartID VARCHAR(20) NOT NULL PRIMARY KEY COMMENT 零件号, ParName VARCHAR(100) NOT NULL COMMENT 零件名称, PartPrice FLOAT NOT NULL COMMENT 价格, PartCost FLOAT NOT NULL COMMENT 成本, OrderNumber INT NOT NULL COMMENT 订货量, TotalCost FLOAT NOT NULL COMMENT 总计, StockNumber INT NOT NULL COMMENT 库存量, LowestStockNumber INT NOT NULL COMMENT 最低库存量 ); -- 零件领用单信息表 CREATE TABLE part_apply ( ApplyOrderID VARCHAR(20) NOT NULL PRIMARY KEY COMMENT 领用单编号, OrderID VARCHAR(20) NOT NULL COMMENT 修理单编号, RepairPeopleId VARCHAR(20) NOT NULL COMMENT 修理工工号, PartID VARCHAR(20) NOT NULL COMMENT 零件号, PartNumber INT NOT NULL COMMENT 零件数量, ApplyDate DATE NULL COMMENT 领用日期, CONSTRAINT fk_apply_order FOREIGN KEY (OrderID) REFERENCES repair_order(OrderID), CONSTRAINT fk_apply_man FOREIGN KEY (RepairPeopleId) REFERENCES repair_people(RepairPeopleId), CONSTRAINT fk_apply_part FOREIGN KEY (PartID) REFERENCES part_stock(PartID) );逻辑说明part_apply是典型的「多对多」桥接表——一个修理单可以用多种零件一种零件可以被多个修理单领用。文档里零件领用单的主键是ApplyOrderID但业务上真正唯一的是「修理单 零件号 领用日期」的组合如果课程设计要求严格可以把这三个字段做成联合唯一索引。参数说明OrderNumber和StockNumber用INT因为零件数量是整数PartPrice和PartCost用FLOAT因为价格可能有小数。文档里TotalCost是订货总计等于OrderNumber * PartCost这个值可以在插入时计算也可以用触发器维护课程设计阶段建议在应用层算简单可控。3. 业务逻辑落地费用计算、订货判断与月报统计建完表只是第一步文档第 4 章「软件功能设计」里明确写了三条核心业务规则修车费计算、零件订货判断、月报统计。这三条规则是课程设计答辩时老师最爱问的也是从「建了表」到「系统能用」的关键跨越。3.1 修车费计算公式的 SQL 实现文档给出的公式是零件费 ∑零件价格 × 耗用数量修理费 ∑小时工资 × 修理工时总计 零件费 修理费。这三个公式涉及part_stock、part_apply、repair_people、repair_order四张表的联合查询。-- 计算指定修理单的费用明细 SELECT ro.OrderID, SUM(ps.PartPrice * pa.PartNumber) AS PartBills, SUM(rp.SalaryPerHour * ro.RepaireHourNum) AS RepaireBills, SUM(ps.PartPrice * pa.PartNumber) SUM(rp.SalaryPerHour * ro.RepaireHourNum) AS TotalAccount FROM repair_order ro JOIN repair_people rp ON ro.RepairPeopleId rp.RepairPeopleId LEFT JOIN part_apply pa ON ro.OrderID pa.OrderID LEFT JOIN part_stock ps ON pa.PartID ps.PartID WHERE ro.OrderID RO2024001 GROUP BY ro.OrderID;逻辑说明这里用LEFT JOIN而不是INNER JOIN是因为有些修理单可能只修理工时、不领零件用内连接会导致这类单子查不出来。SUM聚合零件费和修理费时要注意——如果一张修理单领了多种零件part_apply会有多行SUM(ps.PartPrice * pa.PartNumber)会把所有零件行加起来这是对的但SUM(rp.SalaryPerHour * ro.RepaireHourNum)会因为零件行数被重复计算所以更严谨的写法是把零件费和修理费拆成两个子查询再相加。参数说明PartBills对应文档发票表里的RepaireBills字段注意文档拼写是 Repaire 不是 RepairTotalAccount对应发票表的TotalAccount。如果课程设计要求把计算结果写入发票表就在这个查询外面套一层INSERT INTO invoice ... SELECT ...。3.2 零件订货计划的判断逻辑文档明确写了订货条件零件库存量 最低库存量订货数量 额定订货量。这条规则翻译成 SQL 就是一句WHERE-- 找出需要订货的零件生成订货计划 SELECT PartID, ParName, StockNumber, LowestStockNumber, OrderNumber, PartCost, OrderNumber * PartCost AS TotalCost FROM part_stock WHERE StockNumber LowestStockNumber ORDER BY (LowestStockNumber - StockNumber) DESC;逻辑说明WHERE StockNumber LowestStockNumber是文档原文的订货条件严格照搬。ORDER BY按缺口大小降序排缺口越大越紧急这是实际业务里常见的排序习惯。TotalCost是订货总计等于订货量乘成本对应文档里零件订货计划信息的「总计」字段。参数说明OrderNumber在文档里叫「订货量」注释写的是「额定订货量」意思是每个零件有一个预设的订货批量不是按缺口动态算的。如果你想让系统更智能可以把OrderNumber改成LowestStockNumber - StockNumber但那就偏离文档设计了答辩时可能被问「为什么和需求不一致」。3.3 修理工工资月报的聚合查询文档第 12 条功能是「修理工工资月报」字段包括工号、姓名、修理小时、小时工资、月工资、身份证号码。月工资 修理小时 × 小时工资修理小时需要按月汇总。-- 修理工工资月报以 2024 年 6 月为例 SELECT rp.RepairPeopleId, rp.RepairPeopleName, rp.IdentifyNbr, SUM(ro.RepaireHourNum) AS TotalHours, rp.SalaryPerHour, SUM(ro.RepaireHourNum) * rp.SalaryPerHour AS MonthSalary FROM repair_people rp JOIN repair_order ro ON rp.RepairPeopleId ro.RepairPeopleId WHERE ro.FinishDate BETWEEN 2024-06-01 AND 2024-06-30 GROUP BY rp.RepairPeopleId, rp.RepairPeopleName, rp.IdentifyNbr, rp.SalaryPerHour;逻辑说明WHERE用FinishDate而不是RepairDate因为工资应该按完工日期结算这是业务常识文档没明说但实际做账都这么算。GROUP BY必须包含所有非聚合列MySQL 的ONLY_FULL_GROUP_BY模式下漏掉会直接报错。参数说明BETWEEN 2024-06-01 AND 2024-06-30是闭区间包含首尾两天。如果完工日期字段有 NULL文档里FinishDate允许为空这些单子会被BETWEEN自动排除不会计入工资这是合理的——没完工就不该结算。4. 避坑与排查这份课程设计文档里没写但一定会遇到的问题文档本身是设计说明书不是操作手册所以很多实现层面的坑它不会提。下面这几条是我照着这份设计实际建库建表时踩过的按「现象 → 原因 → 解决」整理。4.1 外键建表顺序导致 CREATE TABLE 失败现象执行repair_order建表语句时报ERROR 1215: Cannot add foreign key constraint。原因repair_order的外键指向car_register和repair_people如果这两张表还没建外键约束无法引用不存在的表。解决按依赖顺序建表——先建sys_user、car_register、repair_people、part_stock这些被引用的表再建repair_order、part_apply、part_in_stock这些带外键的表。如果已经建错了先DROP TABLE再按顺序重建。4.2 varchar 主键在 JOIN 时的性能与排序问题现象多表 JOIN 查询时结果顺序和预期不一致比如修理单编号RO10排在RO2前面。原因varchar主键按字典序排序RO10的第二个字符是1RO2的第二个字符是2所以RO10排在前面。这是字符串排序的固有行为不是 bug。解决如果业务要求按编号数值排序要么把编号设计成定长如RO0002、RO0010要么在ORDER BY里用CAST(OrderID AS UNSIGNED)转换。课程设计阶段建议统一编号格式避免答辩时被问「为什么顺序乱了」。4.3 零件费重复计算导致发票金额翻倍现象一张修理单领了 3 种零件算出来的零件费是实际值的 3 倍。原因repair_order和part_apply是一对多关系JOIN 后修理单行会被复制成多行如果SUM里同时包含修理费和零件费修理费会被重复累加。解决把零件费和修理费拆成两个独立子查询各自聚合后再相加或者用SUM(DISTINCT ...)但DISTINCT在多个零件价格相同时会漏算不推荐。最稳妥的写法是子查询。4.4 Access 与 MySQL 的数据类型不兼容现象把文档里的 Access 建表语句直接搬到 MySQL 执行报BLOB/TEXT column used in key specification without a key length。原因Access 的varchar不指定长度时默认是长文本迁到 MySQL 后如果主键用TEXT类型MySQL 不允许 TEXT 列直接做主键除非指定前缀长度。解决所有varchar主键必须指定长度如VARCHAR(20)。文档里没写长度需要自己按业务估。这是从 Access 迁到 MySQL 最常见的翻车点。4.5 日期字段用字符串存储导致 BETWEEN 查询失效现象WHERE FinishDate BETWEEN 2024-06-01 AND 2024-06-30查不到任何数据但表里明明有 6 月的记录。原因FinishDate字段建表时用了VARCHAR而不是DATE存进去的是2024/6/15这种格式字符串比较时2024/6/15和2024-06-01的字符集不同比较结果不可预期。解决日期字段一律用DATE类型插入时用2024-06-15标准格式。如果已经有脏数据先用STR_TO_DATE转换再ALTER TABLE改字段类型。5. 进阶技巧用视图和存储过程把课程设计做出工程味课程设计如果只停留在建表和简单查询答辩时很难拿高分。文档第 6 章提到「数据库访问模块ADO 方式」但业务逻辑模块和界面框架模块都标注「尚未设计实现」。这意味着你可以在这两个方向上加分——把业务规则下沉到数据库层用视图和存储过程实现既符合文档的 ADO 访问思路又能体现对数据库编程的理解。5.1 用视图封装费用计算简化应用层调用应用层每次开发票都要算零件费、修理费、总计如果每次都写多表 JOIN代码重复且容易出错。建一个视图把计算逻辑封装起来CREATE VIEW v_order_cost AS SELECT ro.OrderID, ro.CarSerialNumber, ro.RepairProject, COALESCE(p.PartBills, 0) AS PartBills, rp.SalaryPerHour * ro.RepaireHourNum AS RepaireBills, COALESCE(p.PartBills, 0) rp.SalaryPerHour * ro.RepaireHourNum AS TotalAccount FROM repair_order ro JOIN repair_people rp ON ro.RepairPeopleId rp.RepairPeopleId LEFT JOIN ( SELECT pa.OrderID, SUM(ps.PartPrice * pa.PartNumber) AS PartBills FROM part_apply pa JOIN part_stock ps ON pa.PartID ps.PartID GROUP BY pa.OrderID ) p ON ro.OrderID p.OrderID;逻辑说明子查询p先按修理单聚合零件费外层再用LEFT JOIN关联这样没有领零件的修理单PartBills为 NULL用COALESCE转成 0。视图建好后应用层只需要SELECT * FROM v_order_cost WHERE OrderID ?一行搞定。参数说明COALESCE是标准 SQL 函数MySQL、SQL Server、Oracle 都支持比IFNULL通用。如果课程设计用的是 AccessAccess 不支持CREATE VIEW里的子查询需要改成 Access 的查询设计器方式。5.2 用存储过程实现订货计划自动生成订货计划的逻辑是「查库存低于最低库存的零件按缺口排序输出订货量」用存储过程封装后应用层只需要调用一个CALLDELIMITER // CREATE PROCEDURE sp_generate_order_plan() BEGIN SELECT PartID, ParName, StockNumber, LowestStockNumber, OrderNumber, PartCost, OrderNumber * PartCost AS TotalCost, CASE WHEN StockNumber 0 THEN 紧急 WHEN StockNumber LowestStockNumber * 0.5 THEN 优先 ELSE 常规 END AS PriorityLevel FROM part_stock WHERE StockNumber LowestStockNumber ORDER BY (LowestStockNumber - StockNumber) DESC; END // DELIMITER ;逻辑说明CASE WHEN给订货计划加了优先级——库存为 0 标「紧急」低于最低库存一半标「优先」其余标「常规」。这是文档里没有但实际业务很实用的扩展答辩时可以作为「对原设计的改进」来讲。参数说明DELIMITER //是 MySQL 客户端指令用来临时改语句结束符因为存储过程内部有分号。如果用的是 Navicat 或 DataGrip直接在存储过程编辑器里写BEGIN ... END即可不需要DELIMITER。5.3 验证方法用测试数据跑通全流程建完表和视图后插一组测试数据验证整条链路。先插汽车、修理工、零件再插修理单和领用单最后查视图和存储过程-- 插入测试数据 INSERT INTO car_register VALUES (京A12345, 大众朗逸, 上汽大众, 张三, 13800138000, 北京市朝阳区); INSERT INTO repair_people VALUES (RP001, 110101199001011234, 李四, 50.0, 1990-01-01, 2020-03-01, 北京市海淀区, 13900139000); INSERT INTO part_stock VALUES (P001, 机油滤清器, 80.0, 50.0, 100, 5000.0, 5, 20); INSERT INTO repair_order VALUES (RO2024001, 京A12345, RP001, 更换机油机滤, 2024-06-01, AP001, 2024-06-02, 2.5); INSERT INTO part_apply VALUES (AP2024001, RO2024001, RP001, P001, 1, 2024-06-01); -- 验证费用视图 SELECT * FROM v_order_cost WHERE OrderID RO2024001; -- 预期PartBills80, RepaireBills125, TotalAccount205 -- 验证订货计划 CALL sp_generate_order_plan(); -- 预期P001 库存 5 最低 20优先级「优先」逻辑说明测试数据的顺序必须遵守外键依赖——先插car_register和repair_people再插repair_order最后插part_apply。part_stock的库存设为 5、最低库存设为 20是为了触发订货条件验证存储过程能正确输出。参数说明RepaireBills预期值 125 50.0 × 2.5TotalAccount预期值 205 80 125。如果查出来不是这个数先检查part_apply的PartNumber是不是 1再检查repair_order的RepaireHourNum是不是 2.5。从那以后我每次拿到一份课程设计文档都会先按数据字典把建表语句写出来跑一遍再拿一组边界数据验证业务规则——文档里写得再漂亮跑不通就是纸上谈兵。这份汽车修理管理系统的设计说明书数据字典和 E-R 图部分是实打实能用的业务逻辑部分需要自己补 SQL 实现正好是练手的好材料。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?