新闻详情

新闻详情

首页 / 资讯中心 / 详情

基于C语言与MySQL的超市管理系统数据库课程设计全流程实战

发布时间:2026/9/26 15:34:22来源:尧图网络
基于C语言与MySQL的超市管理系统数据库课程设计全流程实战
简介这份数据库大作业文档面向高校计算机相关专业学生提供一套完整的小型超市管理系统课程设计参考方案适合正在完成数据库原理课程大作业或需要项目实战练手的学习者。资源包内含1个docx文档大小约249KB内容涵盖项目简介、需求分析、编程软件与环境、数据库基本表与E-R图、数据库框架介绍、源代码段分析及问题解决等模块。文档以C语言和SQL为开发语言基于Visual Studio 2013与MySQL数据库配合Navicat可视化工具详细展示了员工表、商品表、货架表、进货表及日销售量表的设计思路并给出实体间一对多关系的E-R图说明。系统分为管理员、员工、顾客三大模块分别实现员工信息查询修改、销售情况查看、商品信息管理与销售记录等功能。读者可从中获取完整的数据库设计流程、表结构定义、连接与查询的API调用示例以及建表、MFC界面调试等常见问题的排错思路。目前已有1727人学习下载适合作为课程设计参考或数据库入门实践资料。1. 从一份 12 页的数据库大作业说起它到底能跑出什么如果你正在做数据库课程设计或者带学生做大作业大概率会遇到一个经典选题——超市管理系统。这份 12 页的文档资料记录的是一个完整的小型超市管理系统从设计到落地的全过程技术栈是 C 语言 MySQL Visual Studio 2013 Navicat用 MFC 做界面通过 MySQL 提供的 C API 完成数据库交互。它不是那种只讲理论的 PPT而是包含了需求分析、E-R 图、建表逻辑、框架分层、核心代码段和踩坑记录的全流程文档。适合谁看三类人第一类是做数据库课程设计的学生需要一份能参照的完整案例第二类是刚接触 MySQL C API 的开发者想看看mysql_real_connect、mysql_store_result这些函数在实际项目里怎么串起来第三类是带课的老师想找一份结构清晰的参考模板。这份资料最值钱的地方不是代码本身而是它把“设计决策”和“翻车记录”都写出来了——比如主外键怎么选、乱码怎么解、并发为什么没做。这些才是一线开发里真正花时间的地方。2. 三层角色与六张表需求怎么落到 E-R 图上2.1 为什么按顾客、员工、管理员三层来切这个系统的需求分析思路很清晰从使用者的视角出发而不是从功能列表出发。顾客关心的是“商品在哪、多少钱”员工关心的是“库存够不够、信息对不对”管理员关心的是“人怎么样、卖得怎么样”。三种角色对应三种数据访问权限和操作范围这种切法在小型系统里非常实用因为它直接决定了后面界面分几个模块、数据库表怎么设计权限字段。常见做法是先把角色定下来再倒推每个角色需要哪些实体和关系。这份资料就是这么干的顾客只读商品表员工读写商品表和个人信息表管理员额外读写员工表和销售统计表。角色边界清楚了后面的表结构和接口设计就不会乱。2.2 六张核心表的字段设计与主键选择资料里列出了六张基本表员工表、商品表、货架表、进货表、日销售量表以及实体间的关联关系。主键选择上员工表用员工编号商品表用商品编号货架表用“编号 商品编号”做联合主键进货表用商品编号日销售量表按日期和商品维度组织。这里有一个值得注意的设计点货架表用了联合主键。为什么因为同一个货架编号可以摆放多种商品同一个商品也可以放在多个货架上所以单独用任何一个字段都唯一不了。联合主键在这里是合理的但也带来一个问题——如果后续要更新货架和商品的对应关系联合主键的修改会比较麻烦。我一般会建议加一个自增的代理主键把业务唯一性交给唯一索引去管这样后续维护会轻松很多。E-R 图部分资料明确了三组关系员工与商品之间是“整理”关系1 对多员工与销售之间是“记录”关系1 对多货架与商品之间是“摆放”关系1 对多。这三组关系基本覆盖了超市日常运营的核心数据流。2.3 建表时主外键的取舍与常见翻车点资料在“问题解决”部分专门提到建表时对主码和外码的选取出现了困难原因是初期没有完全考虑清楚表之间的关系。这是数据库课程设计里最高频的翻车点之一。具体表现是先建了表后来发现关联查询对不上回头改主键结果外键约束报错数据已经插进去了删也删不干净。我的建议是建表之前先把 E-R 图上的每一条关系都翻译成一句“谁引用谁”的话然后按被引用的表先建、引用的表后建的顺序写 DDL。下面是一个参考的建表顺序和关键字段-- 先建被引用的基础表 CREATE TABLE employee ( emp_id VARCHAR(20) PRIMARY KEY, emp_name VARCHAR(50) NOT NULL, emp_password VARCHAR(50) DEFAULT NULL, emp_phone VARCHAR(20), emp_role VARCHAR(20) DEFAULT staff ) ENGINEInnoDB DEFAULT CHARSETgb2312; CREATE TABLE product ( prod_id VARCHAR(20) PRIMARY KEY, prod_name VARCHAR(100) NOT NULL, prod_category VARCHAR(50) NOT NULL, prod_price DECIMAL(10,2) NOT NULL, prod_stock INT NOT NULL DEFAULT 0 ) ENGINEInnoDB DEFAULT CHARSETgb2312; -- 再建带外键的关联表 CREATE TABLE shelf ( shelf_id VARCHAR(20), prod_id VARCHAR(20), shelf_pos VARCHAR(50), PRIMARY KEY (shelf_id, prod_id), FOREIGN KEY (prod_id) REFERENCES product(prod_id) ) ENGINEInnoDB DEFAULT CHARSETgb2312; CREATE TABLE purchase ( prod_id VARCHAR(20) PRIMARY KEY, purchase_date DATE NOT NULL, purchase_qty INT NOT NULL, supplier VARCHAR(100), FOREIGN KEY (prod_id) REFERENCES product(prod_id) ) ENGINEInnoDB DEFAULT CHARSETgb2312; CREATE TABLE daily_sales ( sale_date DATE, prod_id VARCHAR(20), sale_qty INT NOT NULL DEFAULT 0, sale_amount DECIMAL(12,2) NOT NULL DEFAULT 0, emp_id VARCHAR(20), PRIMARY KEY (sale_date, prod_id), FOREIGN KEY (prod_id) REFERENCES product(prod_id), FOREIGN KEY (emp_id) REFERENCES employee(emp_id) ) ENGINEInnoDB DEFAULT CHARSETgb2312;字符集这里用了gb2312和资料里SET NAMES GB2312保持一致。如果你用的是 MySQL 8.x建议换成utf8mb4否则中文和特殊符号会有问题。但如果你要复现这份资料的环境那就按它的来后面在连接层统一设置字符集。参数说明emp_id和prod_id用VARCHAR而不是INT是因为资料里用的是编号可能包含字母前缀。DECIMAL(10,2)用于价格保证金额计算不丢精度。daily_sales用(sale_date, prod_id)做联合主键保证同一天同一商品只有一条汇总记录。3. VS2013 里配 MySQL C API环境怎么搭、连接怎么建3.1 头文件和库文件的配置路径资料里明确说了第一步是在 VS2013 里添加 MySQL 提供的数据库连接类库包括头文件和相应的类。具体操作是在项目属性里找到“VC 目录”把 MySQL 安装目录下的include文件夹加到“包含目录”把lib文件夹加到“库目录”。然后在代码里#include mysql.h链接器里加上libmysql.lib。这一步看起来简单但实际配的时候经常出问题。最常见的是 32 位和 64 位对不上——VS2013 默认建的是 Win32 项目而你装的 MySQL 可能是 64 位的链接的时候就会报“无法解析的外部符号”。解决办法是要么把项目改成 x64要么换 32 位的 MySQL 库文件。我一般会先确认 MySQL 的位数然后让项目配置和它保持一致。3.2 连接数据库的核心代码与参数含义资料里给出了几个关键函数mysql_real_connect用于建立连接mysql_query执行增删改查mysql_store_result取回结果集mysql_fetch_field获取列名mysql_fetch_row逐行读取数据。下面是一段完整的连接和查询示例#include mysql.h #include stdio.h int main() { MYSQL *sock mysql_init(NULL); // 初始化连接句柄 if (sock NULL) { fprintf(stderr, mysql_init failed\n); return 1; } // 建立连接host, user, password, db, port, unix_socket, client_flag if (mysql_real_connect(sock, localhost, root, 123456, supermarket, 0, NULL, 0) NULL) { fprintf(stderr, connect failed: %s\n, mysql_error(sock)); mysql_close(sock); return 1; } // 设置字符集解决中文乱码 mysql_query(sock, SET NAMES GB2312); // 执行查询 if (mysql_query(sock, SELECT prod_id, prod_name, prod_price FROM product)) { fprintf(stderr, query failed: %s\n, mysql_error(sock)); mysql_close(sock); return 1; } MYSQL_RES *res mysql_store_result(sock); // 取回结果集 if (res NULL) { fprintf(stderr, store result failed: %s\n, mysql_error(sock)); mysql_close(sock); return 1; } MYSQL_ROW row; while ((row mysql_fetch_row(res)) ! NULL) { printf(ID: %s, Name: %s, Price: %s\n, row[0], row[1], row[2]); } mysql_free_result(res); mysql_close(sock); return 0; }逻辑说明mysql_init分配并初始化一个 MYSQL 对象mysql_real_connect的参数依次是主机、用户名、密码、数据库名、端口0 表示默认 3306、unix socketNULL 表示不走 socket、客户端标志0 表示默认。连接成功后立刻执行SET NAMES这一步很关键不设的话中文会变问号。mysql_store_result把整个结果集拉到客户端内存适合数据量不大的场景如果数据量大应该用mysql_use_result逐行读取但那样就不能在读取过程中执行其他查询。参数怎么改host改成你的 MySQL 地址user和password改成你的账号db改成你建的数据库名。如果端口不是 3306把 0 改成实际端口号。3.3 查询结果集的读取与字段处理mysql_fetch_row返回的是一个char**每个元素对应一列的值类型都是字符串。如果你需要把价格转成数字计算得自己用atof或strtod转。mysql_fetch_field返回的是字段元信息包括字段名、类型、长度等适合在需要动态生成表头或者做通用查询界面的时候用。资料里还提到了fd mysql_fetch_field(res)获取列名这个在 MFC 的列表控件里填充表头时很有用。常见做法是先用mysql_num_fields(res)拿到列数然后循环调用mysql_fetch_field把列名塞到 CListCtrl 的列头里。4. 从登录到销售记录三个界面的数据流怎么串4.1 管理员登录与员工信息查询修改管理员界面的入口是一个登录框输入用户名和密码验证通过后才能进入。验证逻辑就是一条SELECT语句在员工表里匹配账号和密码。资料里提到管理员可以按员工编号或姓名查询员工信息还可以修改和添加员工。这里的 SQL 操作覆盖了增删改查四类-- 登录验证 SELECT emp_id, emp_role FROM employee WHERE emp_name 输入的用户名 AND emp_password 输入的密码; -- 按编号查询 SELECT * FROM employee WHERE emp_id E001; -- 按姓名模糊查询 SELECT * FROM employee WHERE emp_name LIKE %张%; -- 修改员工信息 UPDATE employee SET emp_phone 13800000000 WHERE emp_id E001; -- 添加员工 INSERT INTO employee (emp_id, emp_name, emp_password, emp_phone, emp_role) VALUES (E005, 新员工, NULL, 13900000000, staff);注意密码字段允许为 NULL因为资料里说员工初始密码为空进入后可以自己设置。这在真实系统里肯定不合格但作为课程设计它体现了一个“首次登录强制改密”的流程雏形。如果你要改进可以在登录后判断密码是否为空为空就弹窗要求设置新密码。4.2 员工端的商品管理与销售记录员工界面比顾客界面多了修改和添加功能。商品管理部分员工可以查看商品列表、修改价格和库存、添加新商品。销售记录部分员工可以录入当天的销售情况系统会更新日销售量表。这里有一个数据一致性的问题录入销售记录时需要同时更新daily_sales和product的库存。如果两条 SQL 分开执行中间出错就会导致数据不一致。常见做法是用事务包起来START TRANSACTION; INSERT INTO daily_sales (sale_date, prod_id, sale_qty, sale_amount, emp_id) VALUES (CURDATE(), P001, 5, 49.50, E001) ON DUPLICATE KEY UPDATE sale_qty sale_qty 5, sale_amount sale_amount 49.50; UPDATE product SET prod_stock prod_stock - 5 WHERE prod_id P001; COMMIT;ON DUPLICATE KEY UPDATE的作用是如果当天该商品已经有销售记录就累加数量和金额如果没有就插入新记录。这样就不用在应用层先查再判断了。事务保证了两张表要么都成功要么都回滚。4.3 顾客端的商品检索与信息展示顾客界面最简单只做查询不做修改。资料里说顾客可以通过商品名称或类别来查找商品。对应的 SQL 就是带LIKE的模糊查询或者按类别精确匹配-- 按名称模糊查 SELECT prod_name, prod_price, prod_stock FROM product WHERE prod_name LIKE %可乐%; -- 按类别查 SELECT prod_name, prod_price, prod_stock FROM product WHERE prod_category 饮料;顾客端不需要登录所以也没有权限控制。这在小型线下超市的场景里是合理的——顾客在店里的查询终端上操作本身就在物理可控范围内。但如果要做成 Web 或 App就必须加访问控制否则商品成本价之类的敏感字段会暴露。5. 避坑与排查那些资料里踩过的和没写的坑5.1 中文乱码连接层和表定义要一致现象查询出来的中文显示为问号或者乱码。原因连接字符集和表字符集不一致。资料里用的是SET NAMES GB2312但如果你的表建的是utf8mb4这条语句反而会导致乱码。解决先确认表的字符集然后让连接字符集和它保持一致。用SHOW CREATE TABLE product;看表的字符集用SHOW VARIABLES LIKE character%;看服务器的默认字符集。5.2 链接报错“无法解析的外部符号”现象编译通过链接时报错提示mysql_real_connect、mysql_init等函数无法解析。原因库文件没链接上或者位数不匹配。解决检查项目属性里的“附加依赖项”是否加了libmysql.lib检查“库目录”是否指向了正确位数的 MySQL 库文件夹。如果 MySQL 是 64 位而项目是 Win32要么改项目为 x64要么换 32 位的 MySQL。5.3 CString 与 char* 的转换问题现象在 MFC 里用CString拼接 SQL 语句传给mysql_query时报错或乱码。原因CString在 Unicode 环境下是宽字符而 MySQL C API 需要的是窄字符。解决用CStringA或者CT2A宏做转换。资料里提到“对于 C-string 类型的变量在程序调试时会出现错误”说的就是这个。我一般会统一用std::string来拼 SQL最后用.c_str()传给 API避免 MFC 类型和 C 类型混用。5.4 结果集未释放导致内存泄漏现象程序运行一段时间后内存持续增长。原因mysql_store_result返回的结果集没有调用mysql_free_result释放。解决每次mysql_store_result之后在处理完数据后必须mysql_free_result(res)。如果是循环里反复查询更要注意这一点。资料里没有明确写释放的代码但这是必须补上的。5.5 并发访问缺失带来的数据覆盖资料在最后一条问题里写了“还没实现并发访问”。这意味着如果两个员工同时录入销售记录后提交的会覆盖先提交的。解决思路在daily_sales的更新上用ON DUPLICATE KEY UPDATE做累加而不是覆盖或者在应用层加锁。更彻底的做法是用数据库的行锁在事务里SELECT ... FOR UPDATE锁定目标行。但课程设计阶段能把累加逻辑写对就已经比大多数作业强了。6. 进阶技巧把这份大作业改成能写进简历的项目如果你想让这份课程设计在面试里能聊光有增删改查是不够的。我一般会建议做三个改造第一把明文密码改成哈希存储用SHA2函数或者应用层做 MD5 加盐第二把销售记录的录入改成事务 行锁保证并发安全第三加一个简单的销售报表查询按日期范围聚合用GROUP BY和SUM出结果。-- 密码哈希存储示例MySQL 8.x UPDATE employee SET emp_password SHA2(newpassword, 256) WHERE emp_id E001; -- 登录时比对哈希 SELECT emp_id FROM employee WHERE emp_name 输入的用户名 AND emp_password SHA2(输入的密码, 256); -- 销售报表按日期范围统计各商品销售额 SELECT prod_id, SUM(sale_qty) AS total_qty, SUM(sale_amount) AS total_amount FROM daily_sales WHERE sale_date BETWEEN 2024-01-01 AND 2024-01-31 GROUP BY prod_id ORDER BY total_amount DESC;验证方法改完之后用两个客户端同时录入同一商品同一天的销售记录看最终数量是不是两次之和。如果是说明事务和累加逻辑生效了如果只保留了最后一次说明还有覆盖问题。还有一个容易被忽略的点资料里用的是GB2312但现在 MySQL 默认已经是utf8mb4了。如果你在新环境里复现建议统一改成utf8mb4连接层用SET NAMES utf8mb4这样中文、emoji 都不会出问题。改的时候注意表定义、连接设置、客户端显示三处要一致否则乱码会以另一种形式回来。从那以后我每次拿到一个数据库项目第一件事就是确认字符集和位数匹配第二件事就是把所有mysql_store_result后面补上mysql_free_result。这两个习惯帮我省了无数个调试的下午。希望帮到你。本文还有配套的精品资源点击获取
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

收藏!20个AI工具配TaoToken:小白也能成为AI产品经理的settings.json骨架 2026/9/26 16:13:43

收藏!20个AI工具配TaoToken:小白也能成为AI产品经理的settings.json骨架

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
OpenClaw 全套 Skill 使用指南:TaoToken 统一 Key 接入与文件办公自动化实操汇总(含安装包) 2026/9/26 16:13:43

OpenClaw 全套 Skill 使用指南:TaoToken 统一 Key 接入与文件办公自动化实操汇总(含安装包)

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
Traefik 2.3 正式发布:插件系统与 Traefik Pilot 实战配置指南 2026/9/26 16:13:31

Traefik 2.3 正式发布:插件系统与 Traefik Pilot 实战配置指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
深入OpenClaw:那些你可能不知道的“骚操作”——用 TaoToken 统一 Key 打通多工具配置 2026/9/26 16:13:31

深入OpenClaw:那些你可能不知道的“骚操作”——用 TaoToken 统一 Key 打通多工具配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
【MCP探索实践】Redis官方MCP Server配TaoToken:用自然语言驱动Redis的AI原生存储引擎 2026/9/26 16:13:31

【MCP探索实践】Redis官方MCP Server配TaoToken:用自然语言驱动Redis的AI原生存储引擎

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
GitHub Copilot 聊天面板图标全解:新手一看就懂,TaoToken 配置避坑指南 2026/9/26 16:13:31

GitHub Copilot 聊天面板图标全解:新手一看就懂,TaoToken 配置避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉