2021蓝旭工作室暑期第五次培训课-数据库设计文档
数据库设计文档
1. 需求分析设计
目标是设计一款用于餐饮外卖的系统。
如今,外卖市场已经成为O2O模式下的热点。本项目设计了一个外卖点餐系统,为餐厅提供资源配置的解决方案,满足O2O理念的要求。
1.总体需求
用户分为五个角色,分别为:游客,买家,卖家,外卖员,管理员
该系统可根据角色进行业务分类:
- 游客可以不用登录就可以查看店铺和餐饮信息,当然也可以注册称为正式用户
- 买家可以进行餐饮的支付和下单,可以对订单进行管理,以及确认收到餐饮
- 卖家可以申请注册店铺,可以对该店铺的信息进行修改,以及出售餐饮信息的增删改查,也可以查询订单
- 外卖员可以查看订单,可以接单
- 管理员用于审核店铺,餐饮是否合法,以及对用户进行审核,同时可以对店铺、餐饮、用户进行封禁和解封
根据角色的行为可以进行进一步的需求分析:
- 游客的需求分析:
账号注册,用户登录,搜索店铺,搜索和查看餐饮 - 买家的需求分析(包含游客的需求):
餐饮下单,支付结算,确认收到外卖,查看订单信息,删除订单 - 卖家的需求分析:
创建店铺,添加餐饮,删除餐饮,修改餐饮信息,确认订单,注销店铺,查看订单信息 - 外卖员的需求分析:
接单,查看订单信息 - 管理员的需求分析:
审核店铺,审核餐饮,封禁店铺,封禁餐饮
2. 系统功能设想
餐饮外卖系统可以将其划分为对应的6个子系统:搜索子系统、店铺管理子系统、订单管理子系统、餐饮管理子系统子系统、下单子系统、管理员子系统,在此基础上,依据每个系统模块的高内聚低耦合要求还可将各个子系统继续细化划分为更小的功能模块。
2. 概念结构设计
1. 实体定义
实体有:用户(买家,卖家,外卖员,管理员),订单,店铺,餐饮
2. 实体之间的联系
用户(卖家)-订单 一对多 一个卖家可以收到多个订单,但是一个订单不可以有多个卖家
用户(买家)-订单 一对多 一个买家可以下多个订单,但是一个订单不可以有多个买家
用户(外卖员)-订单 一对多 一个外卖员可以接多个订单,但是一个订单不可以有多个外卖员
店铺-餐饮 一对多 一个店铺可以有多个餐饮,但是一个餐饮不可以有多个店铺
卖家-店铺 多对多 一个店铺可以由多个卖家经营,一个卖家可以经营多家店铺
订单-餐饮 多对多 一个订单可以由多个餐饮组成,一个餐饮可以属于多个订单
3. 数据库ER模型
实体属性图
实体联系图(这里为了清楚地表明实体联系,将用户拆分为三个实体来描述,分别为外卖员,买家,卖家)
完整ER图(图画的不好看,大家知道图表示的意思就可以了)
3. 逻辑结构设计
1. 关系模型
用户(主键id,用户名,密码,余额,电话,用户身份鉴别码,用户状态码)
店铺(主键id,店铺名称,店铺介绍,店铺图片路径,店铺地点,店铺状态码)
餐饮(主键id,餐饮名称,餐饮价格,餐饮描述,餐饮图片路径,店铺外键,餐饮制作时间,餐饮状态码)
订单(主键id,买家外键,店铺外键,外卖员外键,订单餐饮总价,创建时间,最早送达时间,最迟送达时间,送达地点,订单状态码)
经营(主键id,店铺外键,卖家外键)
归属(主键id,订单外键,餐饮外键,餐饮数量)
2. 数据库关联关系
- 外键约束1(用户(买家)-订单)tb_order表中的buyer_id对tb_user中的id进行参照,形成两表的关联,表示用户(买家)和订单一对多的关系
- 外键约束2(用户(外卖员)-订单)tb_order表中的deliveryman_id对tb_user中的id进行参照,形成两表的关联,表示用户(外卖员)和订单一对多的关系
- 外键约束3(店铺-订单)tb_order表中的shop_id对tb_shop中的id进行参照,形成两表的关联,表示店铺和订单一对多的关系
- 外键约束4(店铺-餐饮)tb_commodity表中的shop_id对tb_shop中的id进行参照,形成两表的关联,表示店铺和餐饮的一对多的关系
- 外键约束5和6(店铺-卖家)tb_shop_seller表中的shop_id对tb_shop中的id进行参照,tb_shop_seller表中的seller_id对tb_user中的id进行参照,两个外键约束形成了卖家和店铺的多对多的关系
- 外键约束7和8(订单-餐饮)tb_order_commodity表中的order_id对tb_order中的id进行参照,tb_order_commodity表中的commodity_id对tb_commodity中的id进行参照,两个外键约束形成了订单和餐饮的多对多的关系
3. 数据表逻辑设计
1. 用户表逻辑设计
主键id | 用户名 | 密码 | 余额 | 电话 | 用户身份鉴别码 | 用户状态码 |
---|
2. 店铺表逻辑设计
主键id | 店铺名称 | 店铺介绍 | 店铺图片路径 | 店铺地点 | 店铺状态码 |
---|
3. 餐饮表逻辑设计
主键id | 餐饮名称 | 餐饮价格 | 餐饮描述 | 餐饮图片路径 | 店铺外键 | 餐饮制作时间 | 餐饮状态码 |
---|
4. 订单表逻辑设计
主键id | 买家外键 | 店铺外键 | 外卖员外键 | 订单餐饮总价 | 创建时间 | 最早送达时间 | 最迟送达时间 | 送达地点 | 订单状态码 |
---|
5. 管理表逻辑设计
主键id | 店铺外键 | 卖家外键 |
---|
6. 归属表逻辑设计
主键id | 订单外键 | 餐饮外键 | 餐饮数量 |
---|
以上的表设计前五张表均满足BCNF范式,第六张表满足第二范式(在第五部分第二节评价物理结构中会有说明)
4. 物理结构设计
1. 确定数据库的物理结构
1.确定数据库管理系统及其宿主语言
数据库管理系统使用的是MySQL8.0
宿主语言使用的是结构化查询语言SQL
2. 定义数据库、表及字段的命名规范
- 数据库命名全小写
- 表命名全小写,以tb_开头,以下划线分割单词
- 字段全小写,以下划线来分割单词
3. 选择合适的存储引擎
鉴于InnoDB 存储引擎以下几个优点:
- 在事务上具有优势,即支持具有提交、回滚和崩溃恢复能力
- InnoDB 存储引擎可以有效地降低由于删除和更新导致的锁定
- 可以确保事务的完整提交(Commit)和回滚(Rollback)
- 支持外键、Hash索引和B+树索引
并且考虑到该系统以下的几个特点:
- 每一张表都涉及增删改查操作
- 增删操作相对比较频繁
- 对数据一致性和事务一致性要求较高
因此,采用InnoDB作为6张表的存储引擎
4. 关系模式存取方法选择
B+树索引和hash索引:因为采用的是InnoDB存储引擎,而该引擎对索引的实现虽然支持B+树索引和Hash索引,但是该引擎只允许用户创建B+树索引,hash索引是由引擎自己决定的。也就是说,当InnoDB注意到某些索引值被使用非常频繁的时候,它会在内存中基于B+树索引之上再创建一个哈希索引,使得B+树索引也具有哈希索引的优点。这是一个完全自动,内部的行为,无法进行人为的干预。所以索引类型上面只能选用B+树索引
聚簇存取方法的选择:同样因为采用的是InnoDB存储引擎,该引擎要求有且只有一个聚簇索引,并且这个聚簇索引通常选用主键。当然如果没有主键,那么就选用唯一性且不为空的索引,若还是没有唯一性索引那InnoDB就自己创建一个虚拟字段,即默认自增字段row_id作为聚簇索引。而该系统中所有的表均有主键,因此,聚簇索引就是每个表的主键。
5. 为表中的字段选择合适的数据类型
选取规则:
- 当一个列可以选择多种数据类型时,应该优先考虑数字类型,其次是日期和二进制类型,最后是字符类型
- 对于相同级别的数据类型,应该优先选择占用空间小的数据类型
字段数据类型选取(只对比可能用到的数据类型):
数字类型:
数据类型 | 存储空间 | 是否无符号 | 范围 | 选用该类型的数据库字段 |
---|---|---|---|---|
tinyint | 占1字节 | 是 | 范围是0~255 | status check等状态码 |
smallint | 占4字节 | 是 | 范围是0~65535 | num餐饮数量 |
int | 占4字节 | 是 | 范围是0~4294967295 | 主键id和外键id |
decimal | 占4字节 | 否 | 范围是-9999999.99~9999999.99 | 余额,餐饮价格,订单总价 |
日期类型:
数据类型 | 存储空间 | 存储格式 | 范围 | 选用该类型的数据库字段 |
---|---|---|---|---|
datetime | 占8字节 | YYYY-MM-DD HH:MM:SS | 1000-01-01 00:00:00 ~ 9999-12-31 23:59:59 | (新)create_time订单创建时间 |
timestamp | 占4字节 | YYYY-MM-DD HH:MM:SS | 1970-01-01 00:00:00 ~ 2037-12-31 23:59:59 | (旧)create_time订单创建时间 |
time | 占3字节 | HH:MM:SS | -838:59:59——838:59:59 | 餐饮制作时间 最早送达时间 最晚送达时间 |
注意:在第五部分评价物理结构中会介绍为何create_time不使用timestamp类型进行存储,而要使用datetime来存储
字符串类型:
数据类型 | 存储空间 | 是否可变 | 选用该类型的数据库字段 |
---|---|---|---|
char | M 字节,1<=M<=255 | 否 | 用户密码,性别 |
varchar | L+1字节,L< = M 且 1<=M<=255 | 是 | 除密码和性别外所有其他的字符串存储字段 |
6. 各个关系模型对应的关系表及其功能
- 用户关系模式对应tb_user表,用于记录用户信息,包括用户名,密码等
- 店铺关系模式对应tb_shop表,用于记录店铺信息,包括店铺名称等
- 餐饮关系模式对应tb_commodity表,用于记录餐饮信息,包括餐饮名称,价格等
- 订单关系模式对应tb_order表,用于记录订单信息,包括创建时间,送达地点等
- 管理关系模式对应tb_shop_seller表,用于记录店铺和卖家的多对多关系
- 归属关系模式对应tb_order_commodity表,用于记录订单与餐饮的多对多关系
7. 建立数据库物理结构
- 用户信息表tb_user
字段 | 类型 | 长度 | 主键 | 是否可空 | 是否唯一 | 备注 |
---|---|---|---|---|---|---|
id | int | 10 | 是 | 否 | 是 | 主键 |
username | varchar | 70 | 否 | 否 | 是 | 用户名 |
password | char | 32 | 否 | 否 | 否 | 密码,采用MD5加密,因此使用定长的char类型 |
gender | char | 2 | 否 | 是 | 否 | 性别,男或女 |
tel | varchar | 11 | 否 | 否 | 否 | 电话 |
money | decimal | 9 | 否 | 否 | 否 | 余额 |
check | tinyint | 1 | 否 | 否 | 否 | 用户身份鉴别码,买家为1,卖家为2,外卖员为3,管理员为4 |
status | tinyint | 1 | 否 | 否 | 否 | 用户状态,1为正常,2为封禁 |
- 店铺信息表tb_shop
字段 | 类型 | 长度 | 主键 | 是否可空 | 是否唯一 | 备注 |
---|---|---|---|---|---|---|
id | int | 10 | 是 | 否 | 是 | 主键 |
name | varchar | 70 | 否 | 否 | 否 | 店铺名称 |
info | varchar | 255 | 否 | 否 | 否 | 店铺介绍 |
img | varchar | 255 | 否 | 否 | 否 | 店铺图片路径 |
place | varchar | 255 | 否 | 否 | 否 | 店铺地点 |
status | tinyint | 1 | 否 | 否 | 否 | 店铺状态码,0为未审核,1为审核通过,2为审核不通过,3为被封禁 |
- 餐饮信息表tb_commodity
字段 | 类型 | 长度 | 主键 | 是否可空 | 是否唯一 | 备注 |
---|---|---|---|---|---|---|
id | int | 10 | 是 | 否 | 是 | 主键 |
name | varchar | 70 | 否 | 否 | 是 | 餐饮名称 |
price | decimal | 9 | 否 | 否 | 否 | 餐饮价格 |
des | varchar | 255 | 否 | 否 | 否 | 餐饮描述 |
img | varchar | 255 | 否 | 否 | 否 | 餐饮图片路径 |
shop_id | int | 10 | 否 | 否 | 否 | 店铺外键 |
make_time | time | 3 | 否 | 否 | 否 | 餐饮制作时间 |
status | tinyint | 1 | 否 | 否 | 否 | 餐饮状态码,0为未审核,1为可售卖,2为审核不通过,3为被封禁,4为库存不足 |
- 订单信息表tb_order
字段 | 类型 | 长度 | 主键 | 是否可空 | 是否唯一 | 备注 |
---|---|---|---|---|---|---|
id | int | 10 | 是 | 否 | 是 | 主键 |
buyer_id | int | 10 | 否 | 否 | 否 | 买家外键 |
shop_id | int | 10 | 否 | 否 | 否 | 店铺外键 |
deliveryman_id | int | 10 | 否 | 否 | 否 | 外卖员外键 |
sum_money | decimal | 9 | 否 | 否 | 否 | 订单餐饮总价 |
create_time | datetime | 8 | 否 | 否 | 否 | 创建时间 |
earliest_time | time | 3 | 否 | 否 | 否 | 最早送达时间 |
latest_time | time | 3 | 否 | 否 | 否 | 最迟送达时间 |
place | varchar | 255 | 否 | 否 | 否 | 送达地点 |
status | tinyint | 1 | 否 | 否 | 否 | 订单状态码 1为配送中 2为已完成 |
- 店铺买家关系表tb_shop_seller
字段 | 类型 | 长度 | 主键 | 是否可空 | 是否唯一 | 备注 |
---|---|---|---|---|---|---|
id | int | 10 | 是 | 否 | 是 | 主键 |
shop_id | int | 10 | 否 | 否 | 否 | 店铺外键 |
seller_id | int | 10 | 否 | 否 | 否 | 卖家外键 |
- 订单餐饮关系表tb_order_commodity
字段 | 类型 | 长度 | 主键 | 是否可空 | 是否唯一 | 备注 |
---|---|---|---|---|---|---|
id | int | 10 | 是 | 否 | 是 | 主键 |
order_id | int | 10 | 否 | 否 | 否 | 订单外键 |
commodity_id | int | 10 | 否 | 否 | 否 | 餐饮外键 |
num | smallint | 2 | 否 | 否 | 否 | 餐饮数量 |
2. 评价物理结构
字段数据类型的选择原因:
- 主键均采用int类型,并且为自增的。原因是为了防止聚簇索引B+树结构的大规模重构,避免不必要的性能损耗。
- 状态码均采用tinyint类型,状态码通常就是使用数字来表示状态的,不需要占用不必要的存储空间,一个字节无符号的存储足够了
- 订单餐饮数量采用smallint类型,因为考虑到可能存在大规模的场所订外卖(轰趴,party等聚众活动),因此给到2个字节的无符号存储
- 用户余额,餐饮价格以及订单总价采用decimal类型,涉及到金钱的存储要使用decimal类型,这种类型精度较高,不能采用double类型,会有精度损失
- 性别和密码采用char类型,因为char类型对于定长的数据存储检索速度更快,性别只能取男或女,密码的话使用MD5进行加密存储,也是定长的
- 除性别和密码其他需要使用字符串类型进行存储的都使用varchar类型,varchar存储的是可变字符串,除了可节省存储空间外,存取硬盘时也会较有效率。
- 订单创建时间使用的是datetime类型,datetime不会随着该元组信息修改而进行更新,更加适合记录数据的初始创建时间,因此采用datetime,而不使用timestamp类型,timestamp会根据元组更新自动更新时间,更加适合记录数据修改的时间
- 餐饮送达时间使用的是time类型,time类型存储的是小时以下的时间,更加适合外卖时的时间需要
这里解释一下为什么第六张表为什么只要求满足第二范式,而没有向更高的范式追求:
- 第六张表归属表,表示的是餐饮对订单的归属关系,餐饮业我们都知道,这种信息量其实是非常大的,因而插入,删除就会非常频繁。因此采用innodb保证数据一致性和事务一致性。
- 表一般情况下都要设置主键,innodb存储引擎的聚簇索引使用的是主键。而如果追求更高的数据库范式,那么势必就要去掉id字段,让订单和餐饮做一个联合主键,这样的话就满足BCNF范式了。但是,这样做会牺牲数据库性能,甚至导致锁表,造成系统故障。因为主键id是自增的,这样的话,每一次插入一条数据对整个B+树(innodb是采用B+树实现聚簇索引的)破坏重构的影响会最小,每一次只需要在最边上进行树的旋转交换即可。而如果使用联合主键的话,由于不是自增的,是随机的,这将导致整棵B+树,很可能会因为一个数据的插入而导致大范围的重构,引起数据库的性能损耗。而如果在人们吃饭时间,外卖下单高峰期,这样的性能损耗势必会被放大,将直接影响到用户体验。
- MySQL的innodb存储引擎使用MVCC机制和LBCC机制来实现数据和事务一致性.在对数据表进行事务读写的时候会把数据表锁定(如果是根据索引条件进行操作的话是行锁,否则会把整张表锁住).因此,在高并发请求的情况下,数据库处理DML语言的能力或性能不够的话,可能会导致线程阻塞,引起数据库宕机.
- 除了去除主键id之外,其实还可以通过对表的垂直拆分来追求更高范式,但是这样的话查询的时候就要多加一次连表查询,众所周知,连表查询需要进行笛卡尔积,性能开销是比较大的。针对范式模式,查询记录时往往要进行多表连接,而反范式只需在同一张表中查询,当数据量很大的时候,显然反范式的效率会更好,查询速度也就越快。
合理建立索引:
在innodb的索引机制中,建立联合索引的时候是有先后顺序的。在进行查询的时候,优先比对排在第一位的字段,然后依次第二,第三进行比对(innodb的最左前缀原则)。这就导致了,如果我建立联合索引是订单id在前,餐饮id在后,要是根据订单id查询餐饮id还好,图1中可以看出,执行计划使用到了索引,type达到了ref级别,性能上很不错,后面的filtered是百分之百,查询的数据都是有效的。但是根据餐饮id查询订单id却很糟糕,不仅type是ALL全表扫描,而且filtered竟然只有10%,有着近乎90%的性能损耗。显然,性能非常差。因此就要建立合理的索引。采用的方法是再建立一个联合索引餐饮id在前,订单id在后,这样的话就达到和图1一样的效果了
未创建索引
图1
创建索引的SQL语句:
--innodb存储引擎的情况下会自动设置外键为索引,而由于建立联合索引之后就可以完全取代单个索引,因此要先删除事先自动建立的索引
-- 删除索引drop index `order` on tb_order_commodity;drop index commodity on tb_order_commodity;
-- 创建索引create index commodity_order on tb_order_commodity(commodity_id,order_id);
-- 或者alter table tb_order_commodity add index (commodity_id,order_id);
创建索引
图2
多表查询:
尽可能使得join条件是索引列(或者主键,因为在该系统中聚簇索引就是主键索引)以提高性能.同时不要连接太多的表,连表查询性能消耗比较大,适当情况下可以考虑拆分为几个简单查询来处理.如若要使用连接查询,那么就尽可能避免in,or关键字的使用因为可能导致索引失效
这里我使用一个较为复杂的业务来说明–订单信息查询
订单信息比较复杂,需要订单信息,买家信息,店铺信息,外卖员信息,餐饮信息
为了检验SQL的性能,事先使用SQL语句向数据库中创建了每张表近500的数据,下面是添加数据的SQL语句
drop PROCEDURE if proc1 EXISTS
CREATE PROCEDURE proc1 ()
begin
declare i int;
set i=1;
LOOP_LABLE:loop
-- 创建 卖家 买家 外卖员 店铺 餐饮
-- 买家下单
insert into tb_user(username,`password`,`check`,money,gender,`status`,tel) values(concat("买家",i),1234,1,1000.00,'男',1,'13949539733');-- 买家
insert into tb_user(username,`password`,`check`,money,gender,`status`,tel) values(concat("卖家",i),1234,2,1000.00,'男',1,'13949539739');-- 卖家
insert into tb_user(username,`password`,`check`,money,gender,`status`,tel) values(concat("外卖员",i),1234,3,1000.00,'男',1,'13949539730');-- 外卖员
insert into tb_shop(`name`,info,img,place,`status`) values(concat("店铺",i),"店铺信息","img","place",1);-- 注册店铺
insert into tb_shop_seller(seller_id,shop_id) values(i,i);-- 建立店铺和卖家的关系
insert into tb_commodity(`name`,price,des,img,shop_id,make_time,`status`) values(concat("餐饮",i),10.00,"餐饮描述","img",i,now(),1);-- 添加商品
insert into tb_order(buyer_id,shop_id,deliveryman_id,sum_money,create_time,earliest_time,latest_time,place,`status`) values(i,i,i,50.00,now(),now(),now(),"place",i);-- 创建订单
insert into tb_order_commodity(order_id,commodity_id,num) values(i,i,5);-- 建立订单和餐饮的关系set i=i+1;
if i >=500 then leave LOOP_LABLE;
end if;
end loop;
end;
call proc1();
这个是订单信息查询的SQL语句及其执行计划,两张图分别为优化前以及优化后的SQL语句
-- 查询订单信息,多表查询,使用自然连接,涉及5张表的连接,以及一个子查询操作
select o.id as order_id,o.sum_money,o.create_time,o.earliest_time,o.latest_time,o.place,o.`status` as order_status,s.id as shop_id,s.`name`,s.`status` as shop_status ,d.id as deliveryman_id ,d.tel,d.username,d.`status` as deliveryman_status,b.id as buyer_id ,b.tel,b.username,b.`status` as buyer_status,c.`name` as commodity_name,c.make_time from tb_order as o join tb_shop as s on o.shop_id = s.id join tb_user as d on o.deliveryman_id = d.id join tb_user as b on o.buyer_id = b.id join tb_commodity as c on c.id in (select commodity_id from tb_order_commodity where order_id = o.id) where o.id = 84;
图3
-- 查询订单信息,多表查询,使用自然连接,涉及6张表的连接,将其中子查询当作一张表进行连接,从而取代in关键词
select o.id as order_id,o.sum_money,o.create_time,o.earliest_time,o.latest_time,o.place,o.`status` as order_status,s.id as shop_id,s.`name`,s.`status` as shop_status ,d.id as deliveryman_id ,d.tel,d.username,d.`status` as deliveryman_status,b.id as buyer_id ,b.tel,b.username,b.`status` as buyer_status,c.`name` as commodity_name,c.make_time from tb_order as o join tb_shop as s on o.shop_id = s.id join tb_user as d on o.deliveryman_id = d.id join tb_user as b on o.buyer_id = b.id join (select commodity_id from tb_order_commodity where order_id = 84) as oc join tb_commodity as c on c.id = oc.commodity_id where o.id = 84;
图4
显然,从图3中可以看出其中有一个查询过程的type为ALL,也就是全表扫描,这个是由于关键字in引起的,这个in导致了索引失效,因此查询启动了全表扫描。所以,尝试对in关键字进行优化,采取将子查询作为表进行连接,然后再次进行连接的方式进行替代.最终优化结果可以从图4中看出,这种情况下执行计划的type均处很不错的类型.并且filtered也都是100%有效,没有性能损耗.其中,可以从key属性看出,均使用到了主键索引(在innodb中也就是聚簇索引),而关系表则用到了order索引,极大地优化了查询效率.
5. 数据库实施
物理实现
创建数据库及数据表,详细SQL文件如下:
drop database if exists `work`;
create database `work`;
use `work`;
-- 用户表
drop table if exists `tb_user`;
create table tb_user(id int(10) primary key auto_increment comment "用户主键",`username` varchar(70) not null unique comment "用户名",`password` char(32) not null comment "密码",`gender` char(2) comment "性别",`money` decimal(9,2) not null default 0.00 comment "用户余额",tel varchar(11) not null comment "电话",`check` tinyint(1) not null default 1 comment "身份鉴别,买家为1,卖家为2,外卖员为3,管理员为4",`status` tinyint(1) not null default 1 comment "用户状态,1为正常,2为封禁"
)engine=Innodb default charset=utf8;
-- 店铺表
drop table if exists `tb_shop`;
create table tb_shop(id int(10) primary key auto_increment comment "店铺主键",`name` varchar(70) not null unique comment "店铺名称",`info` varchar(255) not null comment "店铺信息",img varchar(255) not null comment "店铺图片路径",place varchar(255) not null comment "店铺地点",`status` tinyint(1) not null default 0 comment "店铺状态,0为未审核,1为审核通过,2为审核不通过,3为被封禁"
)engine=innodb default charset=utf8;
-- 餐饮表
drop table if exists `tb_commodity`;
create table tb_commodity(id int(10) primary key auto_increment comment "餐饮主键",`name` varchar(70) not null comment "餐饮名称",`price` decimal(9,2) not null default 0.00 comment "餐饮价格",`des` varchar(255) not null comment "餐饮描述",img varchar(255) not null comment "餐饮图片路径",shop_id int(10) not null comment "店铺外键",make_time time(3) not null comment "餐饮制作时间",`status` tinyint(1) not null default 0 comment "餐饮状态,0为未审核,1为审核通过,2为审核不通过,3为被封禁,4为库存不足,5为可售卖",constraint shop_commodity foreign key (shop_id) references tb_shop(id) on update cascade on delete cascade
)engine=innodb default charset=utf8;
-- 订单表
drop table if exists `tb_order`;
create table tb_order(id int(10) primary key auto_increment comment "订单主键",buyer_id int(10) not null comment "买家外键",shop_id int(10) not null comment "店铺外键",deliveryman_id int(10) comment "快递员外键",`sum_money` decimal(9,2) not null default 0.00 comment "订单餐饮总价",create_time datetime not null default current_timestamp comment "创建时间",earliest_time time(3) not null comment "最早送达时间",latest_time time(3) not null comment "最晚送达时间",place varchar(255) not null comment "送达地点",
`status` tinyint(1) not null comment "订单状态 1配送中 2已完成",
constraint buyer_order foreign key (buyer_id) references tb_user(id) on update cascade on delete cascade,
constraint shop_order foreign key (shop_id) references tb_shop(id) on update cascade on delete cascade,
constraint deliverman_id foreign key (deliveryman_id) references tb_user(id) on update cascade on delete cascade
)engine=innodb default charset=utf8;
-- 订单-餐饮关系表
drop table if exists `tb_order_commodity`;
create table tb_order_commodity(id int(10) primary key auto_increment comment "主键",order_id int(10) comment "订单外键",commodity_id int(10) comment "餐饮外键",num smallint(2) not null default 1 comment "餐饮数量",constraint `order` foreign key (order_id) references tb_order(id) on update cascade on delete cascade,constraint commodity foreign key (commodity_id) references tb_commodity(id) on update cascade on delete cascade
)engine=innodb default charset=utf8;
-- 店铺-卖家关系表
drop table if exists `tb_shop_seller`;
create table tb_shop_seller(id int(10) primary key auto_increment comment "主键",shop_id int(10) comment "餐饮外键",seller_id int(10) comment "卖家外键",constraint `shop_id` foreign key (shop_id) references tb_shop(id) on update cascade on delete cascade,constraint seller foreign key (seller_id) references tb_user(id) on update cascade on delete cascade
)engine=innodb default charset=utf8;
2021蓝旭工作室暑期第五次培训课-数据库设计文档相关推荐
- 蓝旭工作室2022第五次讨论班Javascript基础
一.JavaScript简介 1.JavaScript背景 JavaScript是一种具有函数优先的轻量级解释型的编程语言,作为开发Web页面的脚本语言而出名. JavaScript最初由Netsca ...
- 2020年蓝旭工作室暑期前端培训班Day1——HTML5 CSS3
HTML5新特性 前言:H5 == HTML5? HTML5是一个标准. H5: 解决方案?看起来炫酷的移动端网页解决方案 技术合集?基于html5, css3, js 基于HTML5的交互网页应用? ...
- 在蓝旭工作室学习的总结
在蓝旭工作室学习的总结 为什么来蓝旭 学习方面 待在工作室一个月以来的感受 怎么学习的 为什么来蓝旭 来蓝旭的真是一段因缘际会, 由于去年的时候,有些自身的原因,错过了加入工作室的机会, 然后这个一直 ...
- 朱晔的互联网架构实践心得S1E9:架构评审一百问和设计文档五要素
朱晔的互联网架构实践心得S1E9:架构评审一百问和设计文档五要素 [下载文本PDF进行阅读] 本文我会来说说我认为架构评审中应该看的一些点,以及我写设计文档的一些心得.助你在架构评审中过五关斩六将,助 ...
- 【转】(五)unity4.6Ugui中文教程文档-------概要-UGUI Interaction Components
原创至上,移步请戳:(五)unity4.6Ugui中文教程文档-------概要-UGUI Interaction Components 4.Interaction Components 本节涵盖了处 ...
- 实体类 接口_spring-boot-route(五)整合Swagger生成接口文档
目前,大多数公司都采用了前后端分离的开发模式,为了解决前后端人员的沟通问题,后端人员在开发接口的时候会选择使用swagger2来生成对应的接口文档,swagger2提供了强大的页面调试功能,这样可以有 ...
- ElasticSearch入门 第五篇:使用C#查询文档
网址:http://www.cnblogs.com/ljhdo/p/4550135.html 这是ElasticSearch 2.4 版本系列的第五篇: ElasticSearch入门 第一篇:Win ...
- 基于JAVA学生会管理系统2021计算机毕业设计源码+系统+数据库+lw文档+部署
基于JAVA学生会管理系统2021计算机毕业设计源码+系统+数据库+lw文档+部署 基于JAVA学生会管理系统2021计算机毕业设计源码+系统+数据库+lw文档+部署 本源码技术栈: 项目架构:B/S ...
- 基于JAVA健身房管理系统演示录像2021计算机毕业设计源码+数据库+lw文档+系统+部署
基于JAVA健身房管理系统演示录像2021计算机毕业设计源码+数据库+lw文档+系统+部署 基于JAVA健身房管理系统演示录像2021计算机毕业设计源码+数据库+lw文档+系统+部署 本源码技术栈: ...
最新文章
- SpringMVC:注解@ControllerAdvice的工作原理
- Theano - 更多的例子
- 站在巨人肩上的.NET Core 2.1
- Volcano plot | 别再问我这为什么是火山图
- spy-debugger 前端调试工具
- android 自定义view 水波纹进度球
- 滚动字幕的源代码(可作滚动公告)
- 大数据常用的五种主要数据挖掘技术
- javascript测试题和参考答案----试题源自牛客网
- 移动前端开发和 Web 前端开发的区别是什么
- Lucene倒排索引简述 番外篇
- C语言 求两个数最小公倍数和最大公因数
- MacOS 单机搭建 Pulsar 集群
- 数据可视化,销量第一的新能源汽车是什么?比亚迪新能源汽车销量接近60万辆
- EasyExcel设置表格样式
- 国立台湾大学_郭彦甫老师_MATLAB课程练习
- Java读取txt格式文件打印到控制台
- 信号坐骑之导引型传输介质
- Delphi中的编译期函数Dec,Inc,Odd,Pred,Succ,Ord,Chr,Low,High,Sizeof【转】
- 如何用 Python 在笔记本上分析 100GB 数据?