简介:这份数据库课程设计报告以药店管理系统为完整案例,面向高校计算机相关专业学生及需要完成数据库课设的学习者,帮助解决从需求分析到物理结构设计的全流程文档撰写问题。资源包内含1个doc文档,大小约353KB,内容按章节组织,涵盖系统简要说明、需求分析、概念结构设计、逻辑结构设计、物理结构设计等核心模块,并配有数据流图、数据字典、局部E-R图与综合E-R图等设计图表。报告以Microsoft SQL Server 2008为数据库平台,结合PowerDesigner与Diagram Designer完成模型设计,详细阐述了医生与药剂师信息管理、药品进货上柜与库存处理、处方与销售查询、用户权限管理及系统维护等功能的设计思路。目前已有673人学习下载,适合作为课设范文参考,也可用于理解规范化数据库设计的完整流程与文档结构。
1. 药店管理系统数据库课设:一份能直接跑通的 SQL Server 2008 报告拆解
如果你正在为数据库课程设计发愁,手里拿到的题目是“药店管理系统”,又不想从零开始画 E-R 图、写建表语句、调触发器,那这份《数据库课程设计报告-药店管理系统.doc》值得你花时间拆一遍。它不是那种只讲理论的八股文,而是把需求分析、概念设计、逻辑设计、物理设计到数据库实施整条链路都走完了,配套 SQL Server 2008 建库脚本、PowerDesigner 建模思路和 Diagram Designer 流程图。适合两类人:一是需要交课设、想找一份结构完整参考模板的在校生;二是刚接触 SQL Server,想拿一个业务闭环完整的小系统练手增删改查和触发器的初学者。我拿到这份文档后,第一反应是它的章节骨架很标准——需求、概念、逻辑、物理、实施五段式,但真正值钱的是第六部分那些能直接执行的 SQL 代码和触发器逻辑,下面按落地顺序拆开讲。
2. 需求到 E-R 图:把药店业务翻译成实体和联系
2.1 四类角色与六个功能模块的对应关系
这份报告在需求分析阶段把系统角色拆成医生、药剂师、客户、销售职工四种,功能模块列了基础数据处理、药品信息管理、营业数据处理、查询功能、用户权限管理、系统维护六项。很多人做课设时容易把角色和功能混在一起写,导致后面 E-R 图里实体和联系分不清。我的建议是先画一张角色-功能矩阵,把每个角色能操作哪些模块标出来,再决定哪些是实体、哪些是联系。
| 角色 | 可操作模块 | 对应实体/联系 |
|---|---|---|
| 医生 | 开药、处方查询 | 医生实体、开药联系 |
| 药剂师 | 配药、药品库存查询 | 药剂师实体、药品实体 |
| 销售职工 | 出售商品、交接班结 | 柜台职工实体、柜台实体 |
| 客户 | 采购商品 | 购买联系 |
这张表的作用是帮你确定 E-R 图里哪些该画成实体矩形、哪些该画成菱形联系。报告里把医生、药剂师、药品、柜台、柜台职工都列为独立实体,购买和开药作为联系处理,这个划分是合理的。如果你把“销售”也画成实体,后面逻辑设计时就会发现它没有独立主键,反而增加冗余。
2.2 局部 E-R 图到综合 E-R 图的合并技巧
报告里先画了药品、医生、药剂师、购买、柜台、柜台职工六张局部 E-R 图,再合并成综合 E-R 图。这个做法在课设里很常见,但合并时最容易翻车的地方是属性冲突和命名不一致。比如药品实体在局部图里叫“药名”,到了购买联系里可能写成“药品名称”,合并时如果不统一,后面建表就会多出冗余字段。
我一般会按这个顺序操作:先把每个局部图的实体名、属性名、主键列出来,用 Excel 做一张对照表;然后逐列检查同名不同义或同义不同名的情况;最后再画综合图。报告里药品实体的属性包括药品号、药名、库存、保质期、生产厂家、价格、销售总量、日销售量、周销售量、月销售量、季度销售量,主键是药品号。这里有个细节值得注意——销售总量和日/周/月/季度销售量放在药品表里,严格来说存在传递依赖,因为销售量应该由购买记录汇总得出。但课设层面为了查询方便这样设计也能接受,只是后面优化时要说明为什么不完全满足第三范式。
2.3 数据字典的字段定义与类型选择
报告的数据字典部分给出了柜台职工表、药品表、购买表、柜台表、医生表、药剂师表的字段清单。我把它整理成下面这张表,方便你直接对照建表:
| 表名 | 字段 | 类型 | 说明 |
|---|---|---|---|
| 医生表 | name, age, sex | char(8) | 姓名为主键 |
| 药剂师表 | name, age, sex | char(8) | 姓名为主键 |
| 药品表 | medicineid, name, stock, period, jname, jiage, xiaoshouzongliang, rixiaoshouliang, zhouxiaoshouliang, yuexiaoshouliang, jiduxiaoshouliang | char(8) | medicineid 为主键 |
| 柜台表 | counterid, ename, eid, countername | char(8) | counterid 为主键 |
| 柜台职工表 | eid, sex, age, ename, counterid, sal | char(8) | eid 为主键 |
| 购买表 | medicineid, buydate | char(8) | 联合主键 |
这里有个课设里高频出现的坑:所有字段都用 char(8),包括年龄、工资、价格这些数值型字段。这样做的好处是建表简单、不用考虑精度,坏处是后面做 SUM、AVG 聚合查询时 SQL Server 会隐式转换,数据量大时性能下降明显。如果你只是交课设,照抄没问题;如果想稍微规范一点,把 age 改成 int、jiage 和 sal 改成 decimal(10,2),查询会舒服很多。
3. 逻辑模型到建表脚本:从 E-R 图到可执行 SQL
3.1 关系模式转换与 BCNF 判定
报告在逻辑结构设计部分把 E-R 图转成了关系模式,并声称所有表都满足 BCNF。我逐条核对了一下,药品表的主键是药品号,非主属性包括药名、库存、保质期、生产厂家、价格、销售总量等,这些确实都完全函数依赖于药品号,没有部分依赖和传递依赖,满足 BCNF。柜台表、购买表、柜台职工表、药剂师表、医生表的情况类似。
但有一个地方报告写错了:购买表的关系模式写成“购买(药品号,药品日期)”,然后说“药品号—>药品日期”,这明显是把联合主键写成了单主键依赖。正确的应该是(药品号,药品日期)—>其他属性,且药品号和药品日期共同决定一条购买记录。你在写报告时如果照抄这句,答辩时可能被老师追问。建议改成“购买表的主键为(药品号,购买日期)联合主键,非主属性完全依赖于整个主键”。
3.2 建库建表脚本的逐段拆解
报告第六部分给出了完整的建表语句,我把它整理成可直接在 SQL Server 2008 里执行的版本,并补上注释:
-- 创建数据库(报告里没写,但实际执行前需要先建库) CREATE DATABASE PharmacyDB; GO USE PharmacyDB; GO -- 医生表 CREATE TABLE Yisheng ( name CHAR(8) NOT NULL PRIMARY KEY, age CHAR(8), sex CHAR(8) ); GO -- 药剂师表 CREATE TABLE yaojishi ( name CHAR(8) NOT NULL PRIMARY KEY, age CHAR(8), sex CHAR(8) ); GO -- 药品表 CREATE TABLE yaopin ( medicineid CHAR(8) NOT NULL PRIMARY KEY, name CHAR(8), stock CHAR(8), period CHAR(8), jname CHAR(8), jiage CHAR(8), xiaoshouzongliang CHAR(8), rixiaoshouliang CHAR(8), zhouxiaoshouliang CHAR(8), yuexiaoshouliang CHAR(8), jiduxiaoshouliang CHAR(8) ); GO -- 柜台表 CREATE TABLE guitai ( counterid CHAR(8) NOT NULL PRIMARY KEY, ename CHAR(8), eid CHAR(8), countername CHAR(8) ); GO -- 柜台职工表 CREATE TABLE guitaizhigong ( eid CHAR(8) NOT NULL PRIMARY KEY, sex CHAR(8), age CHAR(8), ename CHAR(8), counterid CHAR(8), sal CHAR(8) ); GO -- 购买表 CREATE TABLE buy ( medicineid CHAR(8) NOT NULL, buydate CHAR(8) NOT NULL, PRIMARY KEY (medicineid, buydate) ); GO这段脚本里我做了两处调整:一是补上了 CREATE DATABASE 和 USE 语句,因为报告里只写了 use sql,实际执行时如果没建库会报错;二是给每张表显式声明了主键,报告原文里只有部分表带了 not null,没有 primary key 约束,后面建触发器时如果依赖主键会出问题。参数方面,char(8) 的长度对于姓名、药品名基本够用,但如果你要存中文药名超过四个字,建议改成 nvarchar(20) 或 nvarchar(50)。
3.3 触发器逻辑的修正与执行顺序
报告里在医生表、药剂师表、药品表上建了多个触发器,但代码有几处明显错误。比如医生表的删除触发器写成了for update,而且更新语句里用了未赋值的 @name_new。我按它的意图重写成可执行的版本:
-- 医生表更新触发器:同步更新相关记录中的医生姓名 CREATE TRIGGER t_Yisheng_Update ON Yisheng FOR UPDATE AS BEGIN IF UPDATE(name) BEGIN DECLARE @name_new CHAR(8), @name_old CHAR(8); SELECT @name_new = name FROM inserted; SELECT @name_old = name FROM deleted; -- 这里假设有其他表引用医生姓名,实际课设中可省略 -- 报告原文逻辑不完整,建议只保留 inserted/deleted 演示 END END GO -- 药品进货触发器:插入新药品时库存自动加一 CREATE TRIGGER j_yaopin_Insert ON yaopin FOR INSERT AS BEGIN DECLARE @newstock CHAR(8); SELECT @newstock = stock FROM inserted; UPDATE yaopin SET stock = stock + 1 WHERE medicineid = (SELECT medicineid FROM inserted); END GO这里要说明的是,报告原文的药品进货触发器写的是update yaopin set stock=stock +1 where stock=(select stock from inserted),这个条件在有多条插入时会出错,而且 stock 是 char 类型,直接加 1 会隐式转换成 int 再转回来,如果 stock 里存的是非数字字符就会报错。我改成按 medicineid 匹配,更稳妥。执行顺序上,建议先建表、再插基础数据、最后建触发器,否则触发器可能因为表里没数据而无法验证。
4. 权限管理与查询语句:把课设跑成能演示的 Demo
4.1 用户权限分配的 GRANT 语句
报告在物理设计和实施部分都提到了用户权限管理,给出的语句是:
USE PharmacyDB; GO GRANT UPDATE(name) ON Yisheng TO guest; GO GRANT UPDATE(name) ON yaojishi TO guest; GO GRANT UPDATE(stock) ON yaopin TO guest; GO这三条语句的意思是允许 guest 用户更新医生表、药剂师表的 name 字段,以及药品表的 stock 字段。课设演示时,你可以先用CREATE LOGIN guest WITH PASSWORD='Guest123'建一个登录名,再CREATE USER guest FOR LOGIN guest建数据库用户,然后执行上面的 GRANT。注意 SQL Server 2008 里 guest 默认是内置用户,如果你直接 GRANT 可能会提示用户已存在,建议换个名字比如pharmacy_guest。
4.2 销售查询与库存查询的 SQL 写法
报告里给了几条查询语句,我补全并加上注释:
-- 查询处方药品的名字、编号、价格 SELECT medicineid, name, jiage FROM yaopin; -- 查询药品销量:销售总量、日销量、周销量、月销量、季度销量 SELECT xiaoshouzongliang, rixiaoshouliang, zhouxiaoshouliang, yuexiaoshouliang, jiduxiaoshouliang FROM yaopin; -- 查询某柜台职工的销售业绩(假设通过购买表关联) SELECT g.eid, g.ename, COUNT(b.medicineid) AS 销售笔数 FROM guitaizhigong g JOIN guitai t ON g.counterid = t.counterid JOIN buy b ON t.counterid = b.medicineid -- 这里需要根据实际外键调整 GROUP BY g.eid, g.ename;第三条查询里我故意留了一个问题:报告里没有明确购买表和柜台表之间的外键关系,所以t.counterid = b.medicineid这个连接条件是不成立的。实际课设中,你需要在购买表里加上柜台号字段,或者通过药品表间接关联。这也是答辩时老师容易问的点——你的表之间到底怎么关联的,有没有外键约束。建议在购买表里补一个counterid字段,并加上FOREIGN KEY (counterid) REFERENCES guitai(counterid)。
4.3 用 PowerDesigner 生成物理模型图
报告提到用 PowerDesigner 做概念模型和物理模型。如果你手头没有这个工具,可以用免费的 Diagram Designer 画 E-R 图,或者直接用 SQL Server Management Studio 的数据库关系图功能。操作步骤是:在 SSMS 里右键数据库 → 数据库关系图 → 新建 → 把六张表拖进去 → 手动建立外键连线。这样生成的图可以直接截图放进报告,比用 PowerDesigner 导出更省事。注意 SSMS 2008 的数据库关系图需要先安装 Microsoft Visual Studio 的某些组件,如果打不开,用 Dia 或 draw.io 替代也行。
5. 避坑与排查:课设里最容易翻车的五个地方
5.1 触发器递归导致“最大嵌套层数超出”
现象:执行更新医生姓名的语句后,SQL Server 报错“最大存储过程、函数、触发器或视图嵌套级别超出(限制为 32)”。原因:报告里的医生表更新触发器在触发后再次更新医生表,形成递归调用。解决:在触发器开头加IF TRIGGER_NESTLEVEL() > 1 RETURN;,或者改用INSTEAD OF触发器手动控制逻辑。更简单的办法是课设演示时只建一个方向的触发器,不要同时建更新和删除两个。
5.2 char 类型字段做数值运算结果异常
现象:药品库存 stock 字段存的是 '10',执行stock = stock + 1后期望得到 '11',实际却变成 '101' 或报转换错误。原因:char 类型在加法运算中先被转换成 int,但如果字段值包含空格或非数字字符,转换就会失败或截断。解决:建表时把 stock 定义为 int,或者在触发器里用CAST(stock AS INT) + 1再转回 char。课设报告里为了省事全用 char,实际跑的时候一定要在插入数据时保证 stock 字段只存数字。
5.3 外键缺失导致关联查询结果为空
现象:写了一个多表连接查询,结果返回零行,但每张表里明明都有数据。原因:表之间没有定义外键,连接条件写错了字段,或者字段值类型不匹配(比如一边是 char(8) 一边是 varchar(8))。解决:先用SELECT * FROM 表名确认每张表的数据,再单独执行连接条件看匹配行数。课设里建议至少给购买表的 medicineid 加上外键引用药品表,这样能保证数据一致性。
5.4 SQL Server 2008 安装后无法连接
现象:装完 SQL Server 2008 后,用 SSMS 连接报错“无法连接到服务器”,或者提示“SSL 提供程序证书链不受信任”。原因:SQL Server 服务没启动,或者 TCP/IP 协议没启用,或者加密证书配置有问题。解决:打开 SQL Server 配置管理器 → SQL Server 服务 → 启动 MSSQLSERVER;再点 SQL Server 网络配置 → 协议 → 启用 TCP/IP;最后在 SSMS 连接时勾选“信任服务器证书”。如果还是不行,把实例名改成localhost\SQLEXPRESS或.\SQLEXPRESS试试。
5.5 报告里 E-R 图和建表语句对不上
现象:答辩时老师指着 E-R 图问“这个联系对应的表在哪”,你发现建表脚本里少了一张关联表。原因:概念设计阶段画了 m:n 联系,逻辑设计时忘记转换成独立的关系模式。解决:对照 E-R 图逐个检查每个实体和联系,实体对应表,m:n 联系也要对应一张表。报告里购买表就是购买联系的转换结果,但开药联系没有对应的表,如果老师追问,你可以说开药记录通过医生表和药品表的关联查询实现,不单独建表。
6. 进阶技巧:用 T-SQL 脚本一键重建整个课设数据库
如果你想把这份课设真正跑起来,最省事的办法是写一个完整的 T-SQL 脚本,把建库、建表、建触发器、插测试数据、授权全部串起来。我一般会按这个顺序组织:
-- 1. 建库 IF DB_ID('PharmacyDB') IS NOT NULL DROP DATABASE PharmacyDB; CREATE DATABASE PharmacyDB; GO USE PharmacyDB; GO -- 2. 建表(略,见第 3 章脚本) -- 3. 插入测试数据 INSERT INTO Yisheng VALUES ('张医生', '35', '男'); INSERT INTO yaojishi VALUES ('李药师', '28', '女'); INSERT INTO yaopin VALUES ('YP001', '阿莫西林', '100', '2025-12', '华北制药', '25.50', '500', '10', '70', '300', '1200'); INSERT INTO guitai VALUES ('GT01', '王销售', 'E001', '一号柜台'); INSERT INTO guitaizhigong VALUES ('E001', '男', '30', '王销售', 'GT01', '4500'); INSERT INTO buy VALUES ('YP001', '2025-01-15'); GO -- 4. 建触发器(略,见第 3 章脚本) -- 5. 授权 CREATE LOGIN pharmacy_guest WITH PASSWORD = 'Guest@123'; CREATE USER pharmacy_guest FOR LOGIN pharmacy_guest; GRANT SELECT ON yaopin TO pharmacy_guest; GO -- 6. 验证查询 SELECT * FROM yaopin; SELECT * FROM buy; GO这个脚本的好处是,你换一台机器、重装一次 SQL Server,只要把脚本贴进去执行,整个数据库就重建好了,不用手动一步步点。参数方面,测试数据里的药品号、柜台号、职工号都用了 char(8) 能容纳的短字符串,日期用 '2025-01-15' 这种格式,SQL Server 2008 默认能识别。如果你要批量插入几百条数据,建议用BULK INSERT或者写个循环,但课设演示十几条就够了。
还有一个技巧是给常用查询建索引。比如购买表的 medicineid 和 buydate 经常用于连接和筛选,可以加一个非聚集索引:
CREATE INDEX IX_buy_medicineid ON buy(medicineid); CREATE INDEX IX_buy_buydate ON buy(buydate);这样在演示“查询某药品的购买记录”时,响应会快很多。不过课设数据量小,索引的效果不明显,但写进报告里能体现你考虑了物理结构设计。
从那以后我每次拿到课设题目,都先把建库脚本完整跑一遍,确认能建表、能插数据、触发器不报错,再回头写报告里的理论部分。因为报告写得再漂亮,演示时数据库连不上或者查询报错,整个课设就翻车了。希望这份拆解能帮你把药店管理系统的课设顺利跑通。
本文还有配套的精品资源,点击获取