数据库课程设计 - 一个在线购物系统的实现(2)

2015/12/25 | 5分钟阅读 | 更新于 2015/12/25

上来就是(2),因为(1)被我开启了草稿状态,看不到的。

最初我们讨论的商品表是比较简单的,每样商品有商品名,简介,价格,储量,详情,状态,完善点加上创建者,上架时间。直到昨天我突然想起,鞋子有颜色和尺码这两个属性,红色41码和蓝色41码根本就是两种商品,储量各自独立根本不可能互相转化的,而且某些产品不同分类价格都不同的,但是他们毕竟是一件(种,类)商品,详情是一样的,商品名是一样的,商品详情一般也是一份。

那么问题来了,要怎么存储这些商品和各条属性以及对应的价格和数量等的组合,同时又让它们共享商品名和详情以及商品状态呢;顺便在页面上又要怎么布置才会更人性化,更易用呢?

在参考了京东(他们每一个属性组合都是独立的商品,点击不同组合看url可以看出来,但是详情都是一样的)之后,我最直接的反应是,之前的商品表去掉数量和价格等,仅作为索引用,另外新建一个数据表存储商品属性的每一种组合,作为具体的每一件(小类)商品,享有对应的价格和数量。流程上先添加商品(名称,简介,详情,封面,也就是提到的索引),然后进入第二步,逐条创建具体的商品添加进表。在第二步每需要一种组合就点击一次添加,然后输入颜色尺码或者其它属性,最后一次保存。但是这样第二步因为每一条创建的东西过多,界面上无论如何都不会友好(过宽或者过长)。而且这样没有多个属性的商品也得多一条记录,在第一步之后还有判断要不要添加多条具体商品,最后会很繁琐。

有考虑过为属性建一个表,不过意义不是很大,而且这样不方便添加自定义的属性。

现在我又在想,是不是可以反过来呢,先建立具体属性,随便怎么组,都一条条添加进去。之后需要的话再建立商品组。商品组可以不用单独写一张表,只要将其它商品的某一字段指向这组商品中的某一条。而这一条则在这一字段表明是一组商品。这样界面上也是,建立商品的时候可以选择是否和前面某条是一组,如果是的话可以免去商品名称和详情等信息。或者在建立空商品由字段指定这是一个组?

睡觉……

次日更,试了建了一个数据库

CREATE TABLE Goods (
	gid INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
	gname CHAR(128),
	gcate INT(3),
	gprice FLOAT,
	gamount INT(12),
	gabout TEXT,
	gtime DATE,
	gowner INT(10),
	gcover CHAR(120),
	gdetail TEXT,
	gstatus INT(3) NOT NULL, /*0 editing, 10 edited, 20 onsale, 30 stop, 50 del -10 组内商品*/
	ggroup INT NOT NULL, /*0 for group, >0 for child(group gid), <-10 for no group*/
	gcolor CHAR(20),
	gsize CHAR(20),
	g_cls_a CHAR(20),
	g_cls_b CHAR(20),
	g_cls_c CHAR(20)
);

INSERT INTO Goods (
	gname,
	gabout,
	gcate,

	gprice,
	gamount,
	gstatus,
	ggroup,

	gowner,
	gcover,
	gdetail
) VALUES (
	"TEST_ITEM", /*商品名*/
	"TEST_ITEM_ABOUT", /*简介*/
	0, /*分类*/

	19.99, /*价格*/
	172, /*储量*/
	20, /*状态 20 正在销售*/
	-10, /*组 独立商品*/

	1, /*创建人*/
	"/img_store/default_cover.png", /*封面地址*/
	"TEST DETAIL" /*商品详情*/
);

INSERT INTO Goods (
	gname,
	gabout,
	gcate,

	gprice,
	gamount,
	gstatus,
	ggroup,


	gowner,
	gcover,
	gdetail,

	gcolor,
	gsize
) VALUES ( /*此条为分组索引*/
	"TEST_SHOES", /*商品名*/
	"TEST_SHOES_ABOUT", /*简介*/
	1, /*分类*/

	NULL, /*价格*/
	NULL, /*储量*/
	20, /*状态(整个组)20 正在销售*/
	0, /*组 组索引*/

	1, /*创建人*/
	"/img_store/default_cover.png", /*封面地址*/
	"TEST SHOES DETAIL", /*商品详情*/

	NULL, /*颜色 组索引 可省略*/
	NULL /*尺码 组索引 可省略*/
), (
	NULL, /*商品名 分组中商品,可省略*/
	NULL, /*简介 分组中商品,可省略*/
	NULL, /*分类 分组中商品,可省略*/

	97.00, /*价格*/
	56, /*储量*/
	-10, /*状态(整个组)20 正在销售*/
	2, /*组 组号*/

	1, /*创建人*/
	NULL, /*封面地址  分组中商品,可省略*/
	NULL, /*商品详情 分组中商品,可省略*/

	"COLOR_RED", /*颜色*/
	"39" /*尺码*/
), (
	NULL, /*商品名 分组中商品,可省略*/
	NULL, /*简介 分组中商品,可省略*/
	NULL, /*分类 分组中商品,可省略*/

	97.00, /*价格*/
	56, /*储量*/
	-10, /*状态(整个组)20 正在销售*/
	2,  /*组 组号*/

	1, /*创建人*/
	NULL, /*封面地址  分组中商品,可省略*/
	NULL, /*商品详情 分组中商品,可省略*/

	"COLOR_RED", /*颜色*/
	"40" /*尺码*/
), (
	NULL, /*商品名 分组中商品,可省略*/
	NULL, /*简介 分组中商品,可省略*/
	NULL, /*分类 分组中商品,可省略*/

	97.00, /*价格*/
	56, /*储量*/
	-10, /*状态(整个组)20 正在销售*/
	2, /*组 组号*/

	1, /*创建人*/
	NULL, /*封面地址  分组中商品,可省略*/
	NULL, /*商品详情 分组中商品,可省略*/

	"COLOR_RED", /*颜色*/
	"41" /*尺码*/
), (
	NULL, /*商品名 分组中商品,可省略*/
	NULL, /*简介 分组中商品,可省略*/
	NULL, /*分类 分组中商品,可省略*/

	97.00, /*价格*/
	56, /*储量*/
	-10, /*状态(整个组)20 正在销售*/
	2, /*组 组号*/

	1, /*创建人*/
	NULL, /*封面地址  分组中商品,可省略*/
	NULL, /*商品详情 分组中商品,可省略*/

	"COLOR_BLUE", /*颜色*/
	"39" /*尺码*/
), (
	NULL, /*商品名 分组中商品,可省略*/
	NULL, /*简介 分组中商品,可省略*/
	NULL, /*分类 分组中商品,可省略*/

	97.00, /*价格*/
	56, /*储量*/
	-10, /*状态(整个组)20 正在销售*/
	2, /*组 组号*/

	1, /*创建人*/
	NULL, /*封面地址  分组中商品,可省略*/
	NULL, /*商品详情 分组中商品,可省略*/

	"COLOR_BLUE", /*颜色*/
	"40" /*尺码*/
), (
	NULL, /*商品名 分组中商品,可省略*/
	NULL, /*简介 分组中商品,可省略*/
	NULL, /*分类 分组中商品,可省略*/

	97.00, /*价格*/
	56, /*储量*/
	-10, /*状态(整个组)20 正在销售*/
	2, /*组 组号*/

	1, /*创建人*/
	NULL, /*封面地址  分组中商品,可省略*/
	NULL, /*商品详情 分组中商品,可省略*/

	"COLOR_BLUE", /*颜色*/
	"41" /*尺码*/
);

明显太繁琐了,而且结构上也不合理,于是现在我写出了另一种实现。

CREATE TABLE GDetail (
	did INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
	gname CHAR(128) NOT NULL,
	gcate INT(3) NOT NULL,
	gstatus INT(3) NOT NULL, /*0 editing, 10 edited, 20 onsale, 30 stop, 1000 del*/

	gcover CHAR(120),
	gabout TEXT NOT NULL,
	gdetail TEXT NOT NULL,

	gowner INT(10) NOT NULL,

	gtime DATE
);
CREATE TABLE Goods (
	gid INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
	gprice FLOAT,
	gamount INT(12),
	did INT NOT NULL,

	gcolor CHAR(20),
	gsize CHAR(20),
	g_cls_a CHAR(20),
	g_cls_b CHAR(20),
	g_cls_c CHAR(20)
);

INSERT INTO GDetail (
	gname,
	gcate,

	gstatus,

	gabout,
	gdetail,
	gcover,

	gowner
) VALUES (
	"TEST ITEM",
	0, /*分类 0*/

	20, /*状态 20 */

	"TEST ITEM ABOUT",
	"TEST ITEM DETAIL",
	"/img_store/default_cover.png",

	1
),(
	"TEST SHOES",
	1,

	20,

	"TEST SHOES ABOUT",
	"TEST SHOES DETAIL",
	"/img_store/default_cover.png",

	1
);


INSERT INTO Goods (
	gprice,
	gamount,
	did,

	gcolor,
	gsize
) VALUES (
	179.99,
	125,
	1,

	NULL,
	NULL
),(
	98.88,
	28,
	2,

	"COLOR_RED",
	"39"
),(
	98.88,
	15,
	2,

	"COLOR_RED",
	"40"
),(
	98.88,
	27,
	2,

	"COLOR_RED",
	"41"
),(
	96.50,
	20,
	2,

	"COLOR_BLUE",
	"39"
),(
	96.50,
	17,
	2,

	"COLOR_BLUE",
	"40"
),(
	96.50,
	16,
	2,

	"COLOR_BLUE",
	"41"
);

结果就是转了一圈儿又回到了开始的结构上。

© 2026 香蕉引擎故障报告

🌱 Powered by Hugo with theme Dream.

关于

要怎么介绍自己呢,🤔。

很早以前是作为 Web 前端在学习的,但是工作第一年就成为了全干工程师。喜欢尝试各种东西,什么都会一点。

一直很喜欢 Ebiten 游戏引擎 ,特别简洁,用它做过一些小东西,可以查看这个分类 。另外特别推荐这个木鱼 ,是一个相对完整的小玩意儿,包含手搓的一个简单的 UI 框架;支持鼠标和键盘操作;有多语言和主题切换功能;同时支持 Web 端和客户端。它的源代码在 bin16/wooden-fish

主题

网站基于 Hugo,当前使用的是 hugo-theme-dream 主题的修改版 ,根据我的需要,做了一些对 PaperMod 的兼容。

我自己也写过主题 ,但是没有别人写的好看。

正在从我的笔记中往外搬运内容

等待更新:

  • 从《锈湖》中学了些什么东西
  • 我拿 React 写解谜游戏的经过
  • 基于 Pocketbase 的 Pocket Memos
  • 数独!