
数据库设计——订餐系统
文章目录
大致需求
午餐骑士的工作原理
程序→本地供应商列表
供应商→ 饭菜
顾客订单、地址送至服务器
顾客可以选择喜欢一道菜,该菜会显示被喜欢的数量
骑手可以选择接受订单,多个骑手接受按评分高者优先
记录骑手何时交付订单
交付订单后,客户对骑手评价1~5星,可以将骑手添加到自己最爱或者最不爱的名单列表中,为以后选择骑手做依据
人
顾客:顾客编号、姓名、电子邮件地址、手机号、信用卡号(16位数字和有效年/月,记录所有信用卡号,但会标记当前所用卡号,)
供应商:店家编号、名称、店家地址、电子邮件地址、饭菜名称、饭菜价格、饭菜备注(最多1000字)、照片(mediumblob类型)
骑手:骑手编号、姓名、手机号、出生日期
位置坐标
骑手历史位置:骑手编号、骑手位置、时间
1 绪论
1.1 背景



1.2 课题的意义
- 熟悉数据库设计基本步骤紧,进行午餐车系统的设计;
- 理解并运用数据库设计的常见步骤来设计满足给定需求的概念模型(ER模型)和关系数据模型;
- 结合有关的指南对模型进行优化处理;
- 培养系统思维,提升解决复杂工程问题所需的业务问题分析和系统设计能力。
2 应用系统功能设计
2.1 业务操作流程
- 前期宣传,吸引顾客;
- 引入商家并招募骑手,使app有资源有动力;
- 顾客通过app查看本地营业餐厅,选择对应食物,产生待送订单,app从顾客绑定的当前使用的信用卡中扣除对应金额;
- 服务器通过GPS定位、检索功能将待送订单推送给距离较近的骑手,若多人抢单采取评分高即优先的原则进行订单分配,若无人接单,则通过广播加大推送范围,直到有人接单;
- 骑手接单完毕,记录接单时间,且再每分钟都会通过GPS定位发送其当前位置,到数据库记录,直到交付订单并记录交付时间为止;
- 当骑手交付完订单后,顾客可以通过自己对当前订单完成度的满意度对骑手评星(作为骑手的总星级的评级依据),并考虑是否将其加入自己最喜欢或者最不喜欢的骑手名单中。顾客还可以根据自己对所吃食物的满意度,选择是否对食物进行点赞(当点赞时,该食物的热度会加1,取消则减1)。
2.2 系统功能设计
- 检索功能。它能更快的检索到满足顾客需求的餐厅、食物、或者骑手;
- GPS定位系统。在需要时反馈骑手所在位置,方便实时的追踪以及之后的任务调度;
- 广播功能。它能结合检索以及GPS定位系统更省时、更高效地通知附近闲置骑手关于待送订单的信息。
3 数据库设计
3.1 需求分析
3.1.1 数据库的要求
主要任务是建立一个午餐车系统,可以进行餐厅、顾客、食物、骑手、订单等任务的合理分配调度关联。
- 完整性要求:防止不符合语义的数据进入数据库
- 安全性要求:防止用户对数据进行未授权的操作
- 性能要求:实现高并发,允许多个用户同时访问、操作数据库中的数据
- 一致性要求:防止数据库进入不一致状态
- 数据库要求:为防止故障发生导致数据丢失,定期备份
3.1.2 数据字典
-
顾客基本信息

-
信用卡基本信息

-
餐厅基本信息

-
食物基本信息

-
骑手基本信息

-
骑手历史位置基本信息

-
点赞基本信息

-
订单基本信息

-
订单内容基本信息

-
接收订单基本信息

-
交付订单基本信息

-
评价基本信息

3.2 概念结构设计
首先分析整个系统中涉及到的实体及其他们之间的关系,得到局部的ER图,然后进行合并从而得到最终的ER图,见图1。其中:
- 餐厅和食物之间存在拥有关系且为1对多的关系,即1个餐厅对应多种食物而1种食物对应1个餐厅;
- 顾客和食物之间存在点赞关系且为多对多的关系,即1位顾客可以点赞多种食物而1种食物可以被多位顾客点赞;
- 顾客和订单存在上传关系且为1对多的关系,即1位顾客可以上传多个订单而1个订单只能被1位顾客上传;
- 顾客和订单内容存在选择关系且为1对多的关系,即1位顾客可以选择多个订单内容而1个订单内容只能被1位顾客选择;
- 顾客和信用卡存在持有关系且为1对多的关系,即1位顾客可以持有多张信用卡而1张信用卡只能被1位顾客持有;
- 顾客和骑手存在评价关系且为多对多的关系,即1位顾客可以评价多位骑手而1位骑手可以被多位顾客评价;
- 骑手和订单存在接收关系且为1对多的关系,即1位骑手可以接收多个订单而1个订单只能被1位骑手接收;
- 骑手和订单存在交付关系且为1对多的关系,即1位骑手可以交付多个订单而1个订单只能被1位骑手交付;
- 骑手和骑手位置存在定位关系且为1对多的关系,即1位骑手对应多个骑手历史位置而1个骑手历史位置对应1个骑手。

3.3 逻辑结构设计
1. 顾客表信息
顾客编号、姓名、地址、电子邮件、手机号
customer(c_id,cname,c_address,c_email,cphone_num)
主键:顾客编号c_id;
2. 信用卡表信息
信用卡号、顾客编号、有效日期,使用
credit(card_num,c_id,edata,uuseing)
主键:信用卡号card_num
外键:顾客编号c_id对应顾客表中的顾客编号c_id
3. 餐厅表信息
餐厅编号、餐厅名、地址、电子邮件地址
restaurant(r_id,rname,r_address,r_email)
主键:餐厅编号r_id
4. 食物表信息
食物序号、餐厅编号、食物名、单价、食物说明、照片、热度
food(f_id,r_id,fname,unitprice,description,photo,heat)
主键:食物序号f_id
外键:餐厅编号r_id对应餐厅表中的餐厅编号r_id
5. 骑手表信息
骑手编号、姓名、手机号、出生日期、星级
driver(d_id,dname,dphone_num,brith,dstar)
主键:骑手编号d_id
6. 骑手历史位置信息
骑手编号、骑手位置、时间
hposition(d_id,position,time)
主键:(骑手编号,时间)(d_id,time)
外键:骑手编号d_id对应骑手表中的骑手编号d_id
7. 点赞表信息
序号、顾客编号、食物编号
fabulous(num,c_id,f_id)
主键:序号num
外键:顾客编号c_id对应顾客表中的顾客编号c_id
食物编号f_id对应食物表中的食物编号f_id
8. 订单表信息
订单编号、顾客编号、骑手编号、上传时间、接收时间、交付时间、总价
orders(o_id,c_id,d_id,uptime,retime,endtime,total)
主键:订单编号o_id
外键:顾客编号c_id对应顾客表中的顾客编号c_id
骑手编号d_id对应骑手表中的骑手编号d_id
9. 订单内容表信息
订单编号、餐厅编号、食物序号、数量、食物价格、备注
ordercontent(o_id,r_id,f_id,number,prices,remarks)
主键:(订单编号,食物序号)(o_id,f_id)
外键:订单编号o_id对应订单表中的订单编号o_id
餐厅编号r_id对应餐厅表中的餐厅编号r_id
食物编号f_id对应食物表中的食物编号f_id
10. 评价表信息
订单编号、顾客编号、骑手编号、喜爱程度、星级
evaluate(o_id,c_id,d_id,degree,star)
主键:(订单编号,顾客编号)(o_id,c_id)
外键:订单编号o_id对应订单表中的订单编号o_id
顾客编号c_id对应顾客表中的顾客编号c_id
骑手编号d_id对应骑手表中的骑手编号d_id
3.4 物理结构设计与实施
3.4.1 创建数据库
- 创建lunchrider库
create database LunchRider default character set utf8 collate utf8_general_ci;
use lunchrider;
3.4.2 创建表
- 创建顾客表customer
create table customer(
c_id varchar(20) primary key,
cname varchar(20),
c_address varchar(150),
c_email varchar(40),
cphone_num varchar(15)
);
- 创建信用卡表credit
create table credit(
card_num char(16) primary key,
c_id varchar(20),
edata date,
uuseing int,
foreign key (c_id) references customer(c_id)
);
- 创建餐厅表restaurant
create table restaurant(
r_id varchar(20) primary key,
rname varchar(30),
r_address varchar(150),
r_email varchar(40)
);
- 创建食物表food
create table food(
f_id int primary key,
r_id varchar(20),
fname varchar(30),
unitprice float,
description varchar(1000),
photo mediumblob,
heat int,
foreign key (r_id) references restaurant(r_id)
);
- 创建骑手表driver
create table driver(
d_id varchar(20) primary key,
dname varchar(20),
dphone_num varchar(15),
brith date,
dstar float
);
- 创建骑手历史位置表hposition
create table hposition(
d_id varchar(20),
position text,
time datetime,
primary key (d_id,time),
foreign key (d_id) references driver(d_id)
);
- 创建点赞表fabulous
create table fabulous(
num int primary key auto_increment,
c_id varchar(20),
f_id int,
foreign key (c_id) references customer(c_id),
foreign key (f_id) references food(f_id)
);
- 创建订单表orders
create table orders(
o_id varchar(30) primary key,
c_id varchar(20),
d_id varchar(20),
uptime datetime,
retime datetime,
endtime datetime,
total float,
foreign key (c_id) references customer(c_id),
foreign key (d_id) references driver(d_id)
);
- 创建订单内容表ordercontent
create table ordercontent(
o_id varchar(30),
r_id varchar(20),
f_id int,
number int,
prices float,
remarks text,
primary key (o_id,f_id),
foreign key (o_id) references orders(o_id),
foreign key (r_id) references restaurant(r_id),
foreign key (f_id) references food(f_id)
);
- 创建评价表evaluate
create table evaluate(
o_id varchar(20),
c_id varchar(20),
d_id varchar(20),
degree int,
star float,
primary key (o_id,c_id),
foreign key (o_id) references orders(o_id),
foreign key (c_id) references customer(c_id),
foreign key (d_id) references driver(d_id)
);
3.4.3 插入基本数据
- 对顾客表customer、信用卡表credit、餐厅表restaurant、食物表food、骑手表driver、订单表orders、订单内容表ordercontent进行插入数据
insert into customer(c_id,cname,c_address,c_email,cphone_num) values('c0001','小明','花园小区3栋401','123@163.com','12345678901');
insert into customer(c_id,cname,c_address,c_email,cphone_num) values('c0002','小敏','欧洲花园1栋302','456@163.com','12345678910');
insert into credit(card_num,c_id,edata,uuseing) values('1234567','c0001','2025-9-2',1);
insert into credit(card_num,c_id,edata,uuseing) values('2345678','c0002','2028-10-13',0);
insert into restaurant(r_id,rname,r_address,r_email) values('r0001','五谷鱼粉','西华中学200米路南','wuguyufen@163.com');
insert into restaurant(r_id,rname,r_address,r_email) values('r0002','肯德基','龙茂广场1楼105室','kendeji@163.com');
insert into food(f_id,r_id,fname,unitprice,description,photo,heat) values(1,'r0001','招牌鱼粉',10,'内有大量鱼块,味美,辣度适中',LOAD_FILE('D:\zhaopai.jpg'),0);
insert into food(f_id,r_id,fname,unitprice,description,photo,heat) values(2,'r0001','玉米鱼粉',8,'内玉米粒,香糯可口,味美,无辣可自行添加',LOAD_FILE('D:\yumi.jpg'),0);
insert into food(f_id,r_id,fname,unitprice,description,photo,heat) values(3,'r0002','鸡翅',5,'内含两个,有可乐、香辣、奥尔良、原味四种口味',LOAD_FILE('D:\jichi.jpg'),0);
insert into food(f_id,r_id,fname,unitprice,description,photo,heat) values(4,'r0002','牛肉汉堡',20,'分量足,适合成人点,口味可以自行选择',LOAD_FILE('D:\hanbao.jpg'),0);
insert into driver(d_id,dname,dphone_num,brith,dstar) values('d0001','李威','15268430894','1996-5-4',5);
insert into driver(d_id,dname,dphone_num,brith,dstar) values('d0002','张华','15268940865','1994-6-24',5);
insert into orders(o_id,c_id,d_id,uptime,retime,endtime,total) values('o0001','c0001',null,now(),null,null,15);
insert into orders(o_id,c_id,d_id,uptime,retime,endtime,total) values('o0002','c0002',null,now(),null,null,25);
insert into ordercontent(o_id,r_id,f_id,number,prices,remarks) values('o0001','r0001',1,1,10,'不要葱');
insert into ordercontent(o_id,r_id,f_id,number,prices,remarks) values('o0001','r0002',3,1,5,'奥尔良风味');
insert into ordercontent(o_id,r_id,f_id,number,prices,remarks) values('o0002','r0002',3,1,5,'香辣味道');
insert into ordercontent(o_id,r_id,f_id,number,prices,remarks) values('o0002','r0002',4,1,20,'麻辣');
- 展示一下食物表中的效果(发现图片并没有正常插入)

*解决:
1)将food表中photo属性列选中,选择为图像,并点击载入选择对应的图片

2)发现插入成功

3)若想在表给内显示图片,可以点击查看→Display→在网格中显示图像

4)重复1)、2)操作

5)记得保存

3.4.4 创建视图
- 创建顾客_餐厅视图c_restaurant
create view c_restaurant(餐厅编号,餐厅名,地址,电子邮件地址)
as
select r_id,rname,r_address,r_email
from restaurant
with check option;
- c_restaurant视图界面

- 创建餐厅_食物视图r_food
(由于餐厅数目可能较多,所以本次以插入的两条餐厅数据建立两个餐厅_食物视图r_food1、r_food2)
create view r_food1(食物序号,食物名,单价,食物说明,照片,热度)
as
select f_id,fname,unitprice,description,photo,heat
from c_restaurant,food
where c_restaurant.餐厅编号=food.r_id and food.r_id='r0001'
with check option;
create view r_food2(食物序号,食物名,单价,食物说明,照片,热度)
as
select f_id,fname,unitprice,description,photo,heat
from c_restaurant,food
where c_restaurant.餐厅编号=food.r_id and food.r_id='r0002'
with check option;
- r_food1视图界面

- r_food2视图界面

- 创建骑手_订单视图d_orders
create view d_orders(订单编号,姓名,地址,电子邮件,手机号)
as
select o_id,customer.cname,customer.c_address,customer.c_email,customer.cphone_num
from orders,customer
where ifnull(d_id,-1)=-1 and orders.c_id=customer.c_id
with check option;
- d_orders视图界面

- 创建订单_订单内容视图o_ordercontent
(由于未接收订单数目可能较多,所以本次以插入的两条订单数据建立两个订单_订单内容视图o_ordercontent1、o_ordercontent2)
create view o_ordercontent1(餐厅编号,食物序号,数量,食物价格,备注)
as
select ordercontent.r_id,ordercontent.f_id,ordercontent.number,ordercontent.prices,ordercontent.remarks
from d_orders,ordercontent
where d_orders.订单编号=ordercontent.o_id and ordercontent.o_id='o0001'
with check option;
create view o_ordercontent2(餐厅编号,食物序号,数量,食物价格,备注)
as
select ordercontent.r_id,ordercontent.f_id,ordercontent.number,ordercontent.prices,ordercontent.remarks
from d_orders,ordercontent
where d_orders.订单编号=ordercontent.o_id and ordercontent.o_id='o0002'
with check option;
- o_ordercontent1视图界面

- o_ordercontent2视图界面

3.4.5 创建触发器
- 创建点赞_插入触发器
delimiter $
create trigger fabulous_insert
after insert on fabulous
for each row
begin
update food set heat=ifnull(heat,0)+1 where f_id=new.f_id;
end$
delimiter ;
- 点赞表fabulous插入数据
insert into fabulous(c_id,f_id) values('c0001',1);
insert into fabulous(c_id,f_id) values('c0002',3);
- 测试效果

- 创建点赞_删除触发器
delimiter $
create trigger fabulous_delete
after delete on fabulous
for each row
begin
update food set heat=heat-1 where f_id=old.f_id;
end$
delimiter ;
- 点赞表fabulous删除数据
delete from fabulous where c_id='c0002' and f_id=3;
- 测试效果

- 创建骑手评级触发器
这里设置评级规则:骑手初始评级为5星,当顾客通过订单对骑手评价的星级低于当前星级时,当前星级-|差值|*0.01(减后若最终骑手星级低于3星,则将最终骑手星级置于3星);高于当前星级时,当前星级+|差值|*0.02(加后若最终骑手星级高于5星,则将骑手最终星级置于5星)。
delimiter $
create trigger evaluate_insert
after insert on evaluate
for each row
begin
set @dstar1=0;
select dstar into @dstar1 from driver where d_id=new.d_id;
if(@dstar1>new.star)
then
if(@dstar1-0.01*(@dstar1-new.star)>=3)
then
update driver set dstar=dstar-0.01*(dstar-new.star) where d_id=new.d_id;
else
update driver set dstar=3 where d_id=new.d_id;
end if;
elseif(@dstar1<new.star)
then
if(@dstar1+0.02*(new.star-@dstar1)<=5)
then
update driver set dstar=dstar+0.02*(new.star-dstar) where d_id=new.d_id;
else
update driver set dstar=5 where d_id=new.d_id;
end if;
end if;
end$
delimiter ;
- 评价表evaluate插入数据
insert into evaluate(o_id,c_id,d_id,degree,star) values('o0001','c0001','d0001',1,4);
- 测试效果

4 结束语
4.1 收获和体会
1、收获
1)在收到大作业后,通过英文阅读锻炼了自身还通过翻阅资料拔高了一下自身的英语水平;
2)在需求分析阶段,在归纳数据字典的同时,锻炼了自身思维能力,并不断完善数据字典,使之更细致并更科学;
3)在概念结构设计阶段,通过ER图不断结合之前的需求分析结果,在对比中不断完善需求分析的结果,也使ER图更加合理,让自己更细心,并锻炼了自身的综合能力;
4)在逻辑结构设计阶段,通过ER图和数据字典合理规划关系模式,为之后的物理结构设计打下良好的基础,同时锻炼了自我规整能力;
5)在物理结构设计阶段,插入数据、创建视图、创建触发器的环节遇到了不晓得问题,但都通过翻阅资料、网络学习自我解决,锻炼了自我的代码功底以及自我学习能力。
2、体会
在学习的路上自己还有诸多不足,所以应该戒骄戒躁,一步步脚踏实地,以虚心的态度不断从外界摄取营养,通过不断的学习去弥补自身的不足,不断地超越自身、发掘自身潜力。
4.2 总结和展望
通过本次数据库设计,我发现了一些自己以前不知道的优点,也暴露了一些自身的缺点,优点合理利用可以更好、更快地进步,而克服并改掉缺点更能是自己得到质的飞跃。所以很感谢老师布置的大作业,虽然在完成大作业的时候耗费了许多精力,但是也得到了诸多收获,并受益良多,我会谨记,并逐步提升自我。
在本次课程大作业完成之后,我也对未来产生了一些展望。在之后的日子中我会不断学习一些更深入的数据库知识及代码,并结合实例去进一步巩固它们。通过不断深入的学习,我相信,对于以后的数据库应用,我能更快、更高效地理解并实现。
更多推荐

所有评论(0)