KingbaseES工厂管理系统数据库课设:完整建表脚本与避坑指南
简介这份数据库课程设计文档面向计算机相关专业学生与数据库初学者围绕工厂管理系统这一经典课题提供从需求分析到物理实现的完整设计思路。内容涵盖车间、工人、产品、零件、仓库等实体的信息梳理数据流图与数据字典的构建方法E-R模型的概念结构设计以及逻辑结构、物理存储与SQL建表的落地过程可帮助读者理解数据库设计各阶段如何衔接实际业务。资源包共1个doc文件约83KB以Word文档形式呈现便于阅读、批注与二次修改。目前已有59人学习浏览。读者可借此获得一份结构完整的课程设计参考方案掌握实体关系建模、关系模式转换与建表语句编写等关键技能适合用于课程作业参考、答辩准备或数据库设计思路梳理。1. 工厂管理系统数据库课设一份能直接跑通的 KingbaseES 建表脚本如果你正在搜“数据库课程设计工厂管理系统”大概率是两种情况要么课设题目刚发下来不知道从哪下手要么已经写了一半卡在 E-R 图转关系模式、或者建表语句跑不起来。这份资源就是一份完整的工厂管理系统课程设计文档从需求分析、数据字典、E-R 模型一路写到物理设计和 SQL 建表脚本最后还附了设计总结。它解决的核心问题不是“教你数据库理论”而是给你一套可以直接参照的课设落地路径——车间、工人、产品、零件、仓库五个实体怎么抽属性、M:N 联系怎么拆中间表、主键外键怎么定、建表语句怎么写。适合计算机专业正在做数据库课设的本科生也适合想拿一个完整案例练手 SQL 的初学者。需要说明的是原文用的是 KingbaseES 5.0但建表语法和 MySQL、PostgreSQL 高度接近稍作调整就能迁移。2. 从需求到 E-R 图五个实体和四类联系的拆解逻辑2.1 为什么先做数据字典再做 E-R 图很多人做课设的习惯是上来就画 E-R 图画完发现属性漏了、联系搞混了又回头改。这份文档的顺序是反过来的先把每个实体的数据字典列清楚再画分 E-R 图最后合并成全局 E-R 图。这个顺序更符合实际工程习惯因为数据字典本质上是对业务字段的盘点字段没盘清楚实体和联系就是空中楼阁。原文的数据字典覆盖了车间、员工、产品、零件、仓库五张核心表外加车间-零件、产品-零件、零件-仓库、产品-仓库四张联系表以及一张工厂信息表。每张表都标了属性名、存储代码、类型、长度和备注。比如车间表用cjbh char(2)存车间编号员工表用ygbh char(3)存职工号产品表用cpbh char(3)存产品编号。这些字段命名用的是拼音首字母缩写虽然在实际项目里不推荐但课设场景下很常见答辩时老师也能看懂。这里有一个容易被忽略的点原文在数据字典阶段就把联系表单独列出来了比如“车间—零件数据字典”只有cjbh和ljbh两个字段。这意味着设计者已经提前想好了 M:N 联系要拆成独立的关系表而不是等到逻辑结构设计阶段再临时补。这个习惯值得学因为课设答辩时老师经常会问“你这个多对多联系怎么实现的”提前在数据字典里体现出来回答起来更有底气。2.2 全局 E-R 图里四类联系的识别方法原文的全局 E-R 图涉及五个实体工厂、车间、员工、产品、零件、仓库实际上工厂和仓库可以视为两个独立实体。它们之间的联系可以归为四类第一类是“所属”联系。工厂和车间是 1:N一个工厂有多个车间一个车间只属于一个工厂。车间和员工也是 1:N一个车间有多个工人一个工人只属于一个车间。这类联系在转关系模式时把“1”端的主键放到“N”端作为外键即可。第二类是“生产”联系。车间和产品是 M:N一个车间生产多种产品一种产品也可以由多个车间生产。车间和零件同样是 M:N。这类联系必须拆成独立的中间表表中至少包含两个外键分别指向两端的主键。第三类是“组成”联系。产品和零件是 M:N一个产品由多个零件组成一个零件也可以装配到多种产品中。原文在逻辑结构设计里写的是“1:n 表产品(产品号,价格) 表零件(产品号,零件号,重量,价格)”这里其实有笔误产品和零件应该是 M:N需要拆成cplj(cpbh, ljbh)这样的中间表。建表脚本里也确实建了cplj表说明最终实现是对的只是文字描述部分写岔了。第四类是“保管”联系。仓库和产品、仓库和零件都是 M:N产品和零件可以存入多个仓库一个仓库也可以存放多种产品和零件。原文分别建了cpck(cpbh, ckbh)和ljck(ljbh, ckbh)两张中间表。把这四类联系理清楚E-R 图转关系模式就是套规则的事1:N 联系把主键放过去M:N 联系拆中间表1:1 联系随便放哪边都行。课设里最常考的就是 M:N 的拆分这份文档给了四个完整的例子照着抄都不会错。2.3 分 E-R 图到全局 E-R 图的合并技巧原文先画了分 E-R 图包括车间-零件、产品-零件、零件-仓库、产品-仓库、车间-工厂、员工-车间、车间-产品七张局部图然后合并成一张全局 E-R 图。这个做法在课设里很加分因为答辩时老师能看到你的推导过程而不是直接甩一张最终图。合并的时候注意两个问题。第一是实体冲突如果两张分 E-R 图里同一个实体用了不同的属性名合并时要统一。比如车间在“车间-工厂”图里可能叫“车间号”在“车间-产品”图里可能叫“车间编号”最终要统一成一个。第二是联系冲突同一个联系如果在多张分图里出现合并后只保留一个。比如“生产”联系在车间-产品和车间-零件两张图里都有全局图里画一次就行但要注意标注清楚是车间和产品之间、还是车间和零件之间。原文的全局 E-R 图把工厂、车间、员工、产品、零件、仓库六个实体和它们之间的联系都画进去了虽然排版有点乱但结构是完整的。如果你要参考这份文档画自己的 E-R 图建议用 draw.io 或者 Visio 重新画一遍把实体用矩形、联系用菱形、属性用椭圆标清楚答辩时视觉效果会好很多。3. 逻辑结构设计与建表脚本从 E-R 图到 SQL 的完整落地3.1 关系模式转换的规则和原文对照逻辑结构设计的任务是把 E-R 图转成关系模式。原文列出的关系模式包括工厂(厂名, 厂长名)、车间(车间号, 车间主任, 地址, 电话)、工人(职工号, 姓名, 年龄, 性别, 工种)、产品(产品号, 价格)、零件(零件号, 重量, 价格)、仓库(仓库号, 仓库保管员, 姓名, 电话)以及若干联系表。对照建表脚本实际建了十张表factory、cj、yg、cp、lj、cjlj、cplj、ck、ljck、cpck。其中factory对应工厂表cj对应车间表yg对应员工表cp对应产品表lj对应零件表ck对应仓库表剩下四张是中间表。这里有一个细节值得注意原文在逻辑结构设计部分写“1:n 表产品(产品号,价格) 表零件(产品号,零件号,重量,价格)”这个描述把产品和零件的关系写成了 1:N但实际建表时用的是cplj(cpbh, ljbh)中间表说明最终实现是按 M:N 处理的。课设文档里出现这种前后不一致很常见关键是看最终 SQL 脚本因为脚本才是能跑的东西。3.2 建表语句逐条拆解与参数说明原文的建表脚本用的是 KingbaseES 5.0 语法整体结构和 MySQL 非常接近。下面把关键语句拆开讲顺便标注哪些地方需要根据你实际用的数据库调整。-- 工厂表厂名做主键厂长名作为普通字段 create table factory( fname char(12), fmanager char(10), constraint fname_pk primary key(fname) );这条语句建的是工厂表。fname是厂名长度 12 个字符设为主键。fmanager是厂长名长度 10 个字符。constraint fname_pk primary key(fname)是给主键约束起个名字叫fname_pk方便后续维护。如果你用 MySQLchar类型没问题但要注意 MySQL 默认字符集下char(12)能存 12 个字符不是 12 个字节。KingbaseES 和 PostgreSQL 的char也是字符数不是字节数。-- 车间表车间编号做主键 create table cj( cjbh char(2), mc char(3), cjzrbh char(3), bz char(4), constraint cjbh_pk primary key(cjbh) );车间表用cjbh做车间编号长度 2。mc是车间名称长度 3。cjzrbh是车间主任编号长度 3。bz是备注长度 4。这里有个小问题车间名称只给 3 个字符实际用起来可能不够比如“装配车间”四个字就超了。课设场景下可以接受但如果你要扩展建议把mc改成varchar(20)或更长。-- 员工表职工号做主键字段最多 create table yg( ygbh char(3), xm char(8), gz char(1), zwbh char(3), nl char(2), xb char(4), dh char(6), dz char(6), constraint ygbh_pk primary key(ygbh) );员工表字段最多包括职工号、姓名、工种、职位编号、年龄、性别、电话、地址。注意年龄用的是char(2)只能存两位数字如果员工年龄超过 99 就存不下了。实际项目里年龄应该用int或者smallint但课设里用char也能跑。电话用char(6)只能存 6 位固定电话都不够更别说手机号了。这些字段长度偏短是原文的局限你如果照着做建议把电话改成varchar(15)地址改成varchar(50)。-- 产品表产品编号做主键包含车间编号作为外键 create table cp( cpbh char(3), cpmc char(3), jg char(2), cjbh char(2), bz char(4), constraint cpbh_pk primary key(cpbh) );产品表里cjbh是车间编号作为外键指向车间表的主键。但原文没有显式写foreign key约束只是把字段列出来了。如果你想让数据库帮你做参照完整性检查可以加上constraint cp_cj_fk foreign key(cjbh) references cj(cjbh)。不加也能跑但插入数据时如果车间编号不存在数据库不会报错这是课设里常见的坑。-- 零件表零件号做主键 create table lj( ljbh char(3), zl char(3), jg char(1), constraint ljbh_pk primary key(ljbh) );零件表只有三个字段零件号、重量、价格。价格用char(1)只能存一位数字显然不够用实际应该用decimal(10,2)。这是原文的另一个局限你如果照着建表建议把价格字段改成numeric(10,2)或decimal(10,2)。-- 四张中间表只存两个外键没有额外属性 create table cjlj(cjbh char(2), ljbh char(3)); create table cplj(cpbh char(3), ljbh char(3)); create table ljck(ckbh char(3), ljbh char(3)); create table cpck(ckbh char(3), cpbh char(3));这四张中间表分别对应车间-零件、产品-零件、零件-仓库、产品-仓库的 M:N 联系。每张表只有两个字段都是外键。原文没有给中间表设主键实际项目里应该把两个字段组合起来做主键比如constraint cjlj_pk primary key(cjbh, ljbh)这样可以防止重复插入同一条联系记录。3.3 在 KingbaseES 和 MySQL 上分别跑通脚本原文用的是 KingbaseES 5.0如果你手头没有这个环境可以用 MySQL 或 PostgreSQL 替代。下面给出 MySQL 版本的建表脚本字段类型做了适当调整更适合实际运行。-- MySQL 版本工厂管理系统建表脚本 -- 先删后建避免重复执行报错 drop table if exists cpck; drop table if exists ljck; drop table if exists cplj; drop table if exists cjlj; drop table if exists ck; drop table if exists lj; drop table if exists cp; drop table if exists yg; drop table if exists cj; drop table if exists factory; -- 工厂表 create table factory( fname varchar(50) not null, fmanager varchar(30), primary key(fname) ) engineInnoDB default charsetutf8mb4; -- 车间表 create table cj( cjbh varchar(10) not null, mc varchar(50), cjzrbh varchar(10), bz varchar(100), primary key(cjbh) ) engineInnoDB default charsetutf8mb4; -- 员工表 create table yg( ygbh varchar(10) not null, xm varchar(30), gz varchar(10), zwbh varchar(10), nl int, xb varchar(4), dh varchar(20), dz varchar(100), primary key(ygbh) ) engineInnoDB default charsetutf8mb4; -- 产品表 create table cp( cpbh varchar(10) not null, cpmc varchar(50), jg decimal(10,2), cjbh varchar(10), bz varchar(100), primary key(cpbh), constraint cp_cj_fk foreign key(cjbh) references cj(cjbh) ) engineInnoDB default charsetutf8mb4; -- 零件表 create table lj( ljbh varchar(10) not null, zl decimal(10,2), jg decimal(10,2), primary key(ljbh) ) engineInnoDB default charsetutf8mb4; -- 仓库表 create table ck( ckbh varchar(10) not null, glyxm varchar(30), dh varchar(20), primary key(ckbh) ) engineInnoDB default charsetutf8mb4; -- 中间表车间-零件 create table cjlj( cjbh varchar(10) not null, ljbh varchar(10) not null, primary key(cjbh, ljbh), constraint cjlj_cj_fk foreign key(cjbh) references cj(cjbh), constraint cjlj_lj_fk foreign key(ljbh) references lj(ljbh) ) engineInnoDB default charsetutf8mb4; -- 中间表产品-零件 create table cplj( cpbh varchar(10) not null, ljbh varchar(10) not null, primary key(cpbh, ljbh), constraint cplj_cp_fk foreign key(cpbh) references cp(cpbh), constraint cplj_lj_fk foreign key(ljbh) references lj(ljbh) ) engineInnoDB default charsetutf8mb4; -- 中间表零件-仓库 create table ljck( ckbh varchar(10) not null, ljbh varchar(10) not null, primary key(ckbh, ljbh), constraint ljck_ck_fk foreign key(ckbh) references ck(ckbh), constraint ljck_lj_fk foreign key(ljbh) references lj(ljbh) ) engineInnoDB default charsetutf8mb4; -- 中间表产品-仓库 create table cpck( ckbh varchar(10) not null, cpbh varchar(10) not null, primary key(ckbh, cpbh), constraint cpck_ck_fk foreign key(ckbh) references ck(ckbh), constraint cpck_cp_fk foreign key(cpbh) references cp(cpbh) ) engineInnoDB default charsetutf8mb4;这段脚本和原文的主要区别有四点。第一字段类型从char改成了varchar长度也放宽了避免实际插入数据时被截断。第二价格和重量字段改成了decimal(10,2)能存小数更符合实际。第三中间表加了联合主键和外键约束保证数据一致性。第四加了drop table if exists和engineInnoDB方便反复执行。如果你用的是 PostgreSQL 或 KingbaseES把engineInnoDB default charsetutf8mb4去掉即可其他语法基本兼容。执行顺序要注意先建factory、cj、yg、cp、lj、ck这六张主表再建四张中间表因为中间表的外键依赖主表的主键。3.4 插入测试数据验证表结构建完表之后插入几条测试数据验证外键约束和查询逻辑是否正常。-- 插入工厂和车间数据 insert into factory values (第一机械厂, 张厂长); insert into cj values (01, 装配车间, 001, 主车间); insert into cj values (02, 焊接车间, 002, 辅助车间); -- 插入员工数据 insert into yg values (001, 张三, 钳工, 001, 35, 男, 13800138000, 北京市朝阳区); insert into yg values (002, 李四, 焊工, 002, 28, 女, 13900139000, 上海市浦东新区); -- 插入产品和零件数据 insert into cp values (P01, 齿轮箱, 500.00, 01, 主产品); insert into lj values (L01, 2.50, 30.00); insert into lj values (L02, 1.80, 15.00); -- 插入联系数据 insert into cjlj values (01, L01); insert into cjlj values (01, L02); insert into cplj values (P01, L01); insert into cplj values (P01, L02); -- 查询某个产品用了哪些零件 select cp.cpmc, lj.ljbh, lj.zl, lj.jg from cp join cplj on cp.cpbh cplj.cpbh join lj on cplj.ljbh lj.ljbh where cp.cpbh P01;插入数据时要注意外键顺序先插主表再插中间表。如果先插cplj再插cp外键约束会报错。查询语句用了两次join把产品、产品-零件中间表、零件表串起来能查出某个产品用了哪些零件以及零件的重量和价格。这个查询在课设答辩时经常被问到建议提前跑一遍确保结果正确。4. 课设答辩和实际运行中容易翻车的五个坑4.1 字段长度不够导致插入失败现象插入员工姓名“欧阳建国”时数据库报错Data too long for column xm。原文员工表的xm字段是char(8)按理说能存 8 个字符但如果你用的是 MySQL 且字符集不是utf8mb4一个汉字可能占 3 个字节char(8)实际只能存 2 个汉字。原因char类型在 MySQL 里是固定长度长度单位是字符而不是字节但前提是字符集设置正确。如果字符集是latin1汉字根本存不进去如果是utf8一个汉字占 3 个字节char(8)能存 2 个汉字如果是utf8mb4一个汉字占 4 个字节char(8)还是能存 2 个汉字。原文的char(8)存两个汉字都勉强更别说三个字的名字。解决把xm字段改成varchar(30)或varchar(50)字符集用utf8mb4。建表时加上default charsetutf8mb4插入数据前先执行set names utf8mb4。4.2 外键约束导致插入顺序报错现象执行insert into cp values (P01, 齿轮箱, 500.00, 01, 主产品)时报错Cannot add or update a child row: a foreign key constraint fails。原因cp表的cjbh字段有外键约束指向cj表的cjbh。如果cj表里还没有01这个车间编号插入产品数据就会失败。解决先插cj表再插cp表。如果已经插错了可以先set foreign_key_checks 0临时关闭外键检查插完再打开。但更好的做法是养成按依赖顺序插入的习惯工厂 → 车间 → 员工 → 产品/零件 → 仓库 → 中间表。4.3 中间表没有联合主键导致重复数据现象同一个车间和同一个零件的联系被插入了两次查询时出现重复行。原因原文的中间表cjlj只有cjbh和ljbh两个字段没有设主键。数据库不会自动去重同样的组合可以插多次。解决给中间表加联合主键primary key(cjbh, ljbh)这样第二次插入相同组合时会报主键冲突防止重复。如果已经建了表可以用alter table cjlj add primary key(cjbh, ljbh)补上。4.4 E-R 图里 M:N 联系漏拆中间表现象答辩时老师问“车间和产品是多对多你在关系模式里怎么体现的”答不上来或者发现关系模式里没有对应的中间表。原因E-R 图转关系模式时M:N 联系必须拆成独立的关系表不能把两个实体的主键塞到其中一张表里。原文在文字描述部分把产品和零件的关系写成了 1:N但建表脚本里建了cplj中间表说明实现是对的只是文档描述有误。解决检查 E-R 图里所有 M:N 联系确保每个都对应一张中间表。中间表至少包含两个外键分别指向两端的主键。如果中间表还有自己的属性比如“生产数量”也放在中间表里。4.5 KingbaseES 和 MySQL 语法差异导致脚本跑不通现象把原文的建表脚本直接拿到 MySQL 里执行报语法错误。原因KingbaseES 基于 PostgreSQL和 MySQL 在数据类型、约束语法、存储引擎等方面有差异。比如 KingbaseES 的char类型默认长度是 1MySQL 的char必须指定长度KingbaseES 不需要engineInnoDBMySQL 需要。解决如果目标数据库是 MySQL用上面给的 MySQL 版本脚本如果是 KingbaseES 或 PostgreSQL去掉engineInnoDB default charsetutf8mb4把decimal改成numeric其他基本兼容。最稳妥的办法是先在一个测试库里跑一遍确认无误再往正式环境迁移。5. 进阶技巧用视图和存储过程把课设做出工程味课设如果只建表、插数据、写几条查询答辩时很难拿高分。想让老师眼前一亮可以在现有表结构上加两个视图和一个存储过程把“能跑”变成“好用”。先建一个视图把产品、零件、车间的关联信息整合到一起查询时不用每次都写三表连接。-- 视图产品零件明细整合产品、零件、车间信息 create view v_product_part_detail as select cp.cpbh as 产品编号, cp.cpmc as 产品名称, cp.jg as 产品价格, cj.cjbh as 车间编号, cj.mc as 车间名称, lj.ljbh as 零件编号, lj.zl as 零件重量, lj.jg as 零件价格 from cp join cj on cp.cjbh cj.cjbh join cplj on cp.cpbh cplj.cpbh join lj on cplj.ljbh lj.ljbh;这个视图把产品、车间、零件三张主表和一张中间表串起来查某个产品的零件清单时只需要select * from v_product_part_detail where 产品编号 P01不用再写复杂的join。视图的好处是逻辑封装表结构变了只需要改视图定义上层查询不用动。再建一个存储过程实现“根据车间编号查询该车间生产的所有产品及其零件数量”。-- 存储过程根据车间编号统计产品及零件数量 delimiter // create procedure sp_get_workshop_products(in p_cjbh varchar(10)) begin select cp.cpbh as 产品编号, cp.cpmc as 产品名称, count(cplj.ljbh) as 零件数量 from cp join cplj on cp.cpbh cplj.cpbh where cp.cjbh p_cjbh group by cp.cpbh, cp.cpmc; end // delimiter ;调用方式call sp_get_workshop_products(01);。这个存储过程接收一个车间编号参数返回该车间生产的所有产品以及每个产品用到的零件数量。答辩时如果老师问“能不能做一个统计功能”直接跑这个存储过程就行。最后说一个我自己的习惯每次做完课设的建表脚本我都会在本地 MySQL 里完整跑一遍从drop table到insert到select确认没有报错再写进文档。因为课设文档里的 SQL 经常是手写的标点符号、字段名拼写、外键顺序都可能出问题跑一遍能省掉答辩时被老师当场发现错误的尴尬。从那以后我每次交课设前都强制走一遍完整脚本希望这个习惯也能帮到你。本文还有配套的精品资源点击获取