☰
工厂物资管理数据库系统:从E-R图到SQL Server落地全解析
2026/10/2 10:04:24 网站建设 项目流程

简介:一份针对工厂物资管理场景的数据库系统设计报告,适合数据库课程设计、毕业设计或自学数据库建模的读者参考。包体为1个doc文件,压缩包大小仅224KB,内含从需求分析、实体E-R图到逻辑模型、物理模型,再到数据库实施与备份创建的全套设计步骤。资源目前已有397人学习下载,报告目录完整,覆盖供应商、仓库、项目、零件等核心实体,并细化说明了一批数据表、触发器、视图和存储过程的设计思路。通过这份报告可快速理解物资入库、领用、库存预警等业务如何映射为表结构和约束,学习中型业务数据库从概念建模到落地建库的方法;对正在准备答辩或需要评审演示的同学,也可从中提取E-R图、存储过程等核心内容作为汇报素材,并借其文档结构组织自己的课程设计或毕业设计报告。

1. 工厂物资管理数据库系统:从 E-R 图到 SQL Server 2005 落地的一整套方案

如果你正在做数据库课程设计,或者被分配到工厂物资管理这类典型的信息管理系统开发任务,一份能直接照着敲的完整设计报告,能省掉大量查资料和试错的时间。这篇笔记拆的《工厂物资管理数据库系统》设计报告,覆盖了需求分析、概念模型、逻辑模型、物理模型到 SQL Server 2005 实施的完整链路,而且连触发器、视图、存储过程这些容易翻车的细节都给了具体 SQL 代码。它适合正在做数据库课程设计的在校生,也适合刚入手 SQL Server 的中小型工厂信息系统维护人员。整份资源的价值在于,它不是零散的 SQL 片段,而是一条从 E-R 图到可运行数据库的完整路径;照着走,你能在半天内把一个多实体、多联系的物资管理库从图纸变成能跑通的物理库。

2. 需求分析与概念模型:五个核心实体和三类联系的拆解

设计数据库的第一步不是写 SQL,而是把现实业务里的对象和关系理清。这份报告的需求分析做得比较标准,把工厂物资管理拆成了供应商、零件、项目、仓库、职工五个核心实体,外加若干业务联系。我一般拿到这类需求会先画数据流图,明确谁产生数据、谁消费数据,然后才开始画 E-R 图。如果你没有建模经验,建议按「实体—属性—联系」三步走,这和《数据库系统概论》教材里的建模思路一致。

2.1 需求分析要点:零件、供应商、项目、仓库、职工的信息闭环

工厂物资管理的核心,是围绕零件的采购、存储、使用三个环节建立信息记录。报告里提到的数据项很完整:零件需要记录零件号、名称、规格、单价、描述;供应商要记录供应商号、姓名、账号、地址、电话;项目要记录项目号、预算、开工日期;仓库要记录仓库号、面积、电话;职工要记录职工号、姓名、性别、年龄、职称。

这些字段不是拍脑袋定的,每个都对应一个管理问题。比如零件规格和单价,直接关系到成本核算;供应商账号用于财务结算;项目开工日期用于跟踪物资使用进度。我在实际项目中还喜欢再加一个「最后修改时间」字段,方便日后排查数据变更,但课程设计阶段不加也不影响整体评分。

需求分析阶段还有一个容易被忽略的地方:操作需求。报告特别提到系统要支持信息的添加、编辑、删除操作,这直接决定了后面要建触发器来保证数据一致性。如果没有这个需求,外键级别的 ON UPDATE CASCADE 就能解决大部分问题,触发器就不必要了。

2.2 实体 E-R 图与联系描述:多对多、一对多的判定方法

概念模型设计部分,报告依次给出供应商、零件、项目、仓库、职工五个实体的 E-R 图。真正考验建模功底的是实体之间联系的判定。采购部门与供应商的联系,为多个项目提供多种零件,供应商、项目和零件三者之间是多对多的三元联系,用「供应量」作为联系属性。仓库和零件之间是多对多联系,用「库存量」表示某种零件在某仓库的数量。仓库和职工是一对多联系,一间仓库有多个保管员,一个职工只能在一间仓库工作。职工之间还递归地存在领导—被领导联系,即仓库主任领导若干保管员。

我刚开始学建模时,总爱把多对多联系拆成错误的方向。这里有个口诀:如果 A 的一个实例能对应 B 的多个实例,且 B 的一个实例也能对应 A 的多个实例,那就是多对多;只有一边是多个,另一边是唯一,就是一对多。判定清楚了,后面转关系模式才不会出错。这个判定过程也是《数据库系统概论》里 E-R 图例题最喜欢考的点。

2.3 全局 E-R 图合并时的取舍

把五个实体的局部 E-R 图合并成全局结构图时,要注意消除冲突。报告里的做法是把职工拆成普通员工和班长两个子集,因为班长与普通员工之间存在领导关系,这个递归联系在单个实体内部表达会很别扭,拆分后逻辑清晰。合并时还要注意属性归并,比如「电话号码」在仓库资料和供应商资料里都出现,各自的长度还不同,仓库是 15 位,供应商是 7 位,这在逻辑设计阶段就要标记清楚,否则物理实现时容易出错。

提示:全局 E-R 图完成后,一定要回头对照需求分析里的数据流图,逐个确认每个数据项都有归属实体或联系。漏掉一个属性,后面建表时就得多改一轮。

3. 逻辑模型到物理模型:关系模式转换与表结构设计参数

概念模型画完后,下一步是把 E-R 图转成关系模式,这一步直接决定数据库的骨架。报告里的转换遵循了教材上的经典规则:实体转表、联系转表、主键外键按规则确定。转换完毕后,物理模型设计还需要确定数据库文件的物理参数、表字段的精确类型与长度,这些参数看起来琐碎,但直接影响数据库的性能上限和运维方式。

3.1 关系模式转换规则:5 个实体表 + 3 个联系表 + 职工拆分

报告把概念模型转成了 5 个实体关系模式:仓库资料(仓库号、面积、电话号码)、零件资料(零件号、名称、规格、单价、描述)、供应商资料(供应商号、姓名、地址、电话、账号)、项目资料(项目号、预算、开工日期)、职工资料(职工号、姓名、年龄、职称)。

在此基础上,根据联系类型补充了 3 个联系表。多对多的库存关系转成库存量表(仓库号、零件号、库存量),主键是仓库号和零件号的组合。一对多的工作关系转成工作情况表(职工号、仓库号、工作时间),主键为职工号。三元多对多联系转成供应情况表(供应商号、零件号、项目号、供应量),主键是三者组合。最后把职工实体拆成普通员工和班长两个子集,外加领导表(职工号)。

判断联系表是否必要,核心看联系是否携带属性。库存量、供应量都是联系属性,必须单独建表;如果联系不带属性,有时可以合并到实体表中去,但多对多关系在关系模型里必须拆成中间表,不能省。这一点是逻辑设计里最常见的失分点,有些同学把多对多直接建成一个表,查询时就会出现大量冗余。

3.2 物理模型参数:数据文件、日志文件、备份的配置

物理模型设计部分,报告给出了比较具体的配置参数:数据库名称 goodsManagment,数据文件 goodsDAT.MDF,初始大小 3MB,最大空间 20MB,增长量 2MB;日志文件 goodsLOG.LDF,初始 1MB,最大 20MB,增长 2MB;备份设备名为 BACKUP,备份文件 goodsbackup.dat。

从实际部署角度看,这几个参数问题不小。3MB 的初始大小对于这个规模的系统偏小,但 SQL Server 2005 会自动增长,倒也不影响运行。真正要注意的是文件增长策略:按 2MB 固定增长而不是按百分比,优点是增长稳定可预测,缺点是如果数据量突然爆炸,文件会频繁扩展,影响写入性能。生产环境我一般倾向于按 10%~20% 增长,初始大小直接设为预估数据量的 1.5 倍。

日志文件初始只有 1MB,这也是个隐患。工厂物资管理的日志记录频率高,1MB 很快会被占满,频繁自动增长会导致日志碎片。如果你要复现,建议把日志初始大小调到 5MB,增长量调到 5MB,避免数据库跑两天就出现日志增长的性能抖动。备份设备路径放在 D 盘,这个策略是对的,备份文件和数据库文件分盘存放,能防止磁盘物理故障时数据全部丢失。

3.3 字段类型选择与主外键设置注意点

表结构设计里,字段类型的选择有几处值得商榷。报告里仓库资料表的仓库号用 int 做主键,合理;但电话号码在仓库资料表用 char(15),在供应商资料表却用 char(7),这在实际业务里站不住脚。手机号、区号加座机号很容易超过 7 位,如果严格按 char(7) 存储,数据入库时会被截断或报错。我一般把电话号码统一设成 varchar(20),既能存固话也能存手机号。

供应商资料表的账号字段用 int 也有隐患。如果账号以 0 开头,int 会让前导零消失,而且超过 10 位的账号(比如某些对公账号)会超出 int 范围。常见做法是改成 varchar(30)。这种问题在课程设计里可能不被扣分,但拿到生产环境就会被打回票。

主外键设置上,库存情况表的建表语句没有显式定义外键,只在供应情况表和工作情况表用了 references 关键字。虽然逻辑模型里说明了主键和外键关系,但物理实现不完整的话,数据完整性就悬了。如果你要照着复现,建议在库存情况表上把(仓库号,零件号)设为主键,同时加上外键约束,否则日后插入一条不存在的零件到库存表,数据库根本不会报错。

提示:逻辑模型里的主键组合,在物理建表时必须用 primary key(字段1, 字段2) 的形式显式声明,否则 SQL Server 不会自动创建复合主键。

4. SQL Server 2005 实施:建库、建表、建索引,一步一坑

到了实施阶段,报告给出了完整 SQL 脚本。从 create database 到建表、建索引、建触发器、建视图、建存储过程,再到修改语句的验证,顺序安排得很合理。这是整个设计里最有参考价值的部分,照着敲就能跑通。我会先给整体顺序,再逐个拆关键的 SQL 代码段。实施过程中踩到的最多的坑,几乎都集中在路径、保留字和字符集这三件事上。

4.1 创建数据库与备份设备:路径、初始大小、增长策略

create database goodsManagment on ( name = goosaDAT, filename = 'c:\SQL\goodsDAT.MDF', size = 3, maxsize = 20, filegrowth = 2 ) log on ( name = 物资管理LOG, filename = 'c:\SQL\goodsLOG.ldf', size = 1, maxsize = 20, filegrowth = 2 )

这段建库脚本里,name 是逻辑文件名,filename 是物理路径,size 是初始大小(MB),maxsize 是容量上限,filegrowth 是自动增长步长。需要注意,filename 指向的目录 c:\SQL 必须提前建好,否则执行会报错。这是新手最常见的翻车点——SQL Server 不会自动创建目录。

备份设备的创建方式是调用系统存储过程:

sp_addumpdevice 'disk', 'BACKUP1', 'D:\sql\goodsbackup1.dat' go backup database goodsManagment to BACKUP1

sp_addumpdevice 的三个参数分别指定设备类型、逻辑名称和物理文件路径。第一个 go 把存储过程和备份语句分隔成独立的批次。这里的坑和建库一样:D:\sql 目录不存在时,sp_addumpdevice 不会报错,但执行 backup 语句时会失败。我在本地复现时习惯先把目录建好再执行,免得排查半天路径问题。

参数调整方面,如果你的机器上 SQL Server 服务账号没有 C 盘写入权限,建库就会失败。常见做法是把路径改到 SQL Server 的数据目录下,或者给服务账号授予目标目录的写权限。

4.2 创建数据表:主键和外键的 SQL 写法

建表脚本比较多,我挑几个有代表性的拆一下。仓库资料表:

create table 仓库资料( 仓库号 int primary key, 面积 int, 电话号码 char(15) )

零件资料表:

create table 零件资料( 零件号 int primary key, 名称 varchar(30), 规格 varchar(20), 电话号码 char(15), 描述 Text, 单价 int )

供应情况表是最有参考价值的,因为它同时包含外键和复合引用:

create table 供应情况表( 供应商号 int references 供应商资料(供应商号), 零件号 int references 零件资料(零件号), 项目号 int references 项目资料(项目号), 供应量 int )

可以看到,这版建表脚本没有显式给供应情况表建复合主键,外键约束也只在供应情况表和工作情况表里出现,库存情况表完全没有外键。我建议你复现时加上主键定义:primary key(供应商号, 零件号, 项目号)。否则数据表就少了唯一性约束,重复插入同一条供应记录也不会报错。

零件资料表里出现了中文列名和描述 Text字段。Text 类型在 SQL Server 2005 里已经标记为过时,用来存大段文本可以,但后续无法直接用普通字符串函数处理。如果你想让系统更容易扩展,可以考虑换成 varchar(max)。字段的中文名不算错,但程序里访问时要用方括号包住,比如select [零件号] from [零件资料]。

4.3 创建非聚集索引与约束

索引部分,报告对所有主键列都建了非聚集索引:

create nonclustered index IX_仓库号 on 仓库资料(仓库号 asc) create nonclustered index IX_零件号 on 零件资料(零件号 asc)

这里有个概念层面的问题:SQL Server 的主键默认就是聚集索引,再建一个同列的非聚集索引,属于重复索引,白占空间。我猜测设计者是想练习索引语法,但实际优化价值为零。真正该建索引的是外键列,比如供应情况表里的供应商号、零件号、项目号,库存情况表里的仓库号和零件号。

外键列不建索引是另一个常见坑。在 SQL Server 里,外键约束不会自动创建索引。你要是在 delete 父表数据时发现性能极差,多半是外键列没索引,导致每条删除都触发全表扫描。所以复现时,我建议给每个外键列都补上非聚集索引,特别是三张联系表的外键列。索引不是越多越好,建在查询频繁的列上才有收益。

4.4 修改语句:update/delete 的常见误用

报告在验证阶段用了多组 update 和 delete 语句,比如:

use goodsManagement go update 供应商资料 set 供应商号 = 1002 where 供应商号 = '2001' go select * from 供应商资料

单看语法没有问题,但实际执行时大概率会失败,因为你在前面建了触发器 goodid,它要求供应商号被修改时同步更新供应情况表,而触发器会受外键约束影响。隐患在于:供应情况表里若存在供应商号 2001 的记录,update 主表触发级联修改时,如果外键约束阻止了即时更新,整个事务会被回滚。

delete 语句同理:

delete from 供应商资料 where 供应商号 = '1002'

如果 1002 在供应情况表里有记录,触发器 good_3 会抛异常并回滚删除,这是设计好的行为,不是 bug。你要是想「先删子表再删主表」,顺序不能反过来。

注意:执行这类修改语句前,先开一个显式事务(begin tran),确认影响行数正确后再 commit。否则一条语句下去,数据全变了却没法快速回滚。

5. 避坑与常见问题:触发器、视图、存储过程的踩坑记录

触发器这部分是整份设计报告里最容易踩坑的地方。报告写了 6 个触发器,覆盖主表更新级联、删除保护两种场景。我在复现这些触发器时踩了四个比较典型的坑,逐个记下来,你会少走很多弯路。

5.1 触发器删除保护的条件判断问题

第一个坑是删除保护触发器的判定条件。以供应商删除保护为例:

create trigger good_3 on 供应商资料 for delete as if exists(select 供应商号 from deleted a where a.供应商号 in (select 供应商号 from 供应情况表)) begin raiserror('因在供应商资料中存在,不得删除此条记录!', 16, 1) rollback transaction end

现象是删除了一条供应情况表里不存在的供应商记录,触发器照样回滚,删不掉任何供应商。原因在于 deleted 表里记录的是所有被删除的行,如果一次删除多条记录,只要其中一条有供应记录,整个事务都会被回滚。解决方法是把判断改成「所有被删记录都不存在关联才允许删除」,或者强制一次只删一条记录并配合 where 条件精确删除。

5.2 修改主键与触发器级联的顺序问题

第二个坑是修改主键时,触发器与外键约束的执行顺序。报告里的 goodid 触发器,在供应商资料表更新时同步修改供应情况表的供应商号。实际执行时,如果子表记录已存在,外键约束会先于触发器检查,导致更新失败,报外键冲突。现象就是明明写了级联触发器,update 还是报错。原因是 SQL Server 的外键约束在触发器之前生效。解决方法是临时禁用外键约束,或者在设计子表外键时直接使用on update cascade,让数据库自己处理级联,反而比触发器更稳。

5.3 视图与存储过程的定义问题

第三个坑在视图和存储过程上。创建视图时,报告用了这样的 SQL:

create VIEW project(供应商姓名, 零件名, 项目号, 零件总价格) as select 姓名, 名称, 项目号, 供应量 * 单价 from 供应商资料, 供应情况表, 零件资料 where 供应商资料.供应商号 = 供应情况表.供应商号 and 供应情况表.零件号 = 零件资料.零件号

这个视图能建成功,但列名和表达式对应关系容易出错。查询时如果直接select * from project,你看到的是供应商姓名、零件名、项目号、零件总价格四列;但如果用 openquery 或程序访问,列名必须写「供应商姓名」而不是「姓名」,很多人在这上面栽跟头。存储过程 lookworker 也存在类似问题:创建时是select 职工号 from 职工资料 where 职工号 = @id,只返回职工号,不返回姓名和职称,实际使用价值有限,建议按需扩展返回列。

5.4 中文表名和保留字引发的低级错误

第四个坑是中文表名和保留字。SQL Server 2005 完全支持中文表名和列名,但必须用方括号括起来。有些同学图省事,在程序代码里直接拼 SQL 字符串,没加方括号,执行就报语法错误。另外,项目资料、零件资料这些表名本身不是保留字,但列名里如果出现name、description这类与系统冲突的词,不加方括号也会报错。复现时我统一用方括号包住所有中文表名和列名,能避免绝大多数低级语法报错。

6. 进阶:触发器的正确验证方法与查询优化

触发器建好后,很多人的第一反应是「建完了就完事」,从来不验证。实际上,触发器的验证比创建更重要。我一般会在执行每个触发器后,用一组正反用例分别验证正常路径和异常路径。以 goodid 为例,我会先准备一条供应商号 1001、在供应情况表里有对应订单的数据,然后执行update 供应商资料 set 供应商号 = 1002 where 供应商号 = 1001。执行完立即查供应情况表,确认关联记录的供应商号也变成了 1002。再接一条反向用例:故意 update 一条在供应情况表里没有记录的供应商,确认能正常更新且不报错。这样一组用例跑完,触发器的行为才算被真正验证过。

存储过程的验证也有个小技巧。lookworker 创建完之后,我会依次测试三个场景:传入存在的职工号、传入不存在的职工号、传入 NULL。第二个场景返回空结果集,这没问题;第三个场景如果程序端没做空值保护,可能会把整张表的职工号都返回出来。这个问题可以通过在存储过程里加if @id is null return来规避。视图的验证更简单,直接查和聚合结果对账。比如 project 视图里的零件总价格,我会用select sum(供应量 * 单价) from 供应情况表 join 零件资料 ...独立算一遍,两边对不上就是视图的 join 条件有问题。

关于索引,我在 4.3 节已经提过,主键列不需要额外建非聚集索引,真正值得建的是外键列和查询条件列。这里再补一层:视图 project 的过滤条件用到供应商号和零件号,你把它俩的索引建上,视图查询速度会有明显提升。索引不是越多越好,覆盖高频查询的列才行,否则只是白白堆空间。

最后一个实战习惯是,复现完整个系统后,把建库脚本、建表脚本、触发器脚本分别存成独立的 .sql 文件,按执行顺序编号。这样以后环境重装或换机器部署,直接按顺序跑一遍就行,不用再对着报告一行行复制。从那以后,我每次拿到类似的设计报告,都会强制走一遍「需求分析 → E-R 图 → 逻辑模型 → 物理模型 → 实施脚本 → 正反用例验证」的完整流程,确认每个对象都能对上,这份资源里的系统就能真正跑起来。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询