Common table structure analysis database design

First, the relationship between the data table tree

Many programmers performing database design when they are encountered tree data relationships, such as a common category table, that is a category, here are several subcategories, such a situation there are certain subclasses of subclasses. When the uncertain category, the user would like to add in any new sub-class category, or delete a category and all sub-categories under it, and later their number is expected to gradually increase, then we will consider the use of a data table to save the data.

Design structure:

name Types of Restrictions Explanation
type_id int No repeat Category identification, primary key
type_name char(50) NOT NULL Type name must be unique
type_father int NOT NULL The category's parent category identification, if the top node is then set to a unique value
type_layer char(6) Defining layer 3, the initial value 000000 Preorder traversal category, mainly to reduce the number of searchable database

Benefits of this design is to facilitate traversal, only one can be retrieved, by providing type_layer traversal order to set, three layers 000000, can be increased if required multiple, each layer is allowed up to 99 sub-categories. 010101 denotes a third layer.

Retrieval: SELECT * FROM Type_table_2 ORDER BY type_layer

Listing record set as follows:

the type_id TYPE_NAME type_father type_layer
. 1 Total class 0 000000
2 Class 11 010000
3 Category 1.1 2 010100
Category3 1.2 2 010200
. 5 Class 21 020000
. 6 Category 2.15 020 100
. 7 Class 31 030000
. 8 category 3.1. 7 030 100
. 9 Type 3.2. 7 030.2 thousand
10 1.1.1 category 3 010 101
......    

Second, the product design information table (attribute table how scalable)

Suppose you are a department store developer of the computer department, one day your boss asks for the company to develop a set of online e-commerce platform, the department store several thousands of products to sell, but at the moment only the intention to facilitate transport in dozens of online sales commodity, of course, the future may continue to increase in the new e-commerce platform on the sale of goods. Now begin to design the product information table of the database platform. Each sale of goods will have the same attributes, such as product number, product name, product Category, information, suppliers, contains several parts, inventory, purchase price, sales price, price.

Product Types Table (Wares_type)

name Types of Restrictions Explanation
type_id int No repeat Category identification, primary key
type_name char(50) NOT NULL Type name must be unique
type_father int NOT NULL The category's parent category identification, if the top node is then set to a unique value
type_layer char(6) Defining layer 3, the initial value 000000 Preorder traversal category, mainly to reduce the number of searchable database

Suppliers table (Wares_provider)

name Types of Restrictions Explanation
provider_id int No repeat Supplier identification, primary key
provider_name char(100) NOT NULL Supplier's name

Product Information Table (Wares_info)

name Types of Restrictions Explanation
wares_id int No repeat Product ID, the primary key
wares_name char(100) NOT NULL product name
wares_type int NOT NULL Commodity type identification, association and Wares_type.type_id
wares_info char(200) Allow for the empty Related Information
provider int NOT NULL Suppliers identification, association and Wares_provider.provider_id
substituted int The initial value of 1 Containing several pieces, the default is 1
stock int The initial value of 0 Inventory, defaults to 0
buy_price money NOT NULL Purchase price
sell_price money NOT NULL Selling price
discount money NOT NULL Price

You took the three examination tables to the boss, the boss hopes to add a picture of the commodity field, but only some products have pictures. OK, you add a haspic of BOOL type field in the product information table (Wares_info), and then built a new table - Picture table (Wares_pic):

Picture table (Wares_pic)

name Types of Restrictions Explanation
pic_id int No repeat Picture ID, the primary key
wares_id int NOT NULL Owned commodity identification, and related Wares_info.wares_id
pic_address char(200) NOT NULL Pictures stored path

After the completion of the development program, fully meet the current requirements of the boss, then officially opened. Over time, the boss wants to introduce new merchandise for sale on this platform, in which certain goods all need to add the "length" of the property. The first round came toss ...... Of course, you follow the old method to add product images table, adds a haslength of BOOL type field in the product information table (Wares_info) in, and built a new table - commodities length table (Wares_length ):

Product length table (Wares_length)

name Types of Restrictions Explanation
length_id int No repeat Picture ID, the primary key
wares_id int NOT NULL Owned commodity identification, and related Wares_info.wares_id
length char(20) NOT NULL Product Description Length

刚刚改完没多久,老板又打算上一批新的商品,这次某类商品全部需要添加“宽度”的属性。你咬了咬牙,又照方抓药,添加了商品宽度表(Wares_width)。又过了一段时间,老板新上的商品中有一些需要添加“高度”的属性,你是不是开始觉得你所设计的数据库按照这种方式增长下去,很快就能变成一个迷宫呢?那么,有没有什么办法遏制这种不可预见性,但却类似重复的数据库膨胀呢?我在阅读《敏捷软件开发:原则、模式与实践》中发现作者举过类似的例子:7.3 “Copy”程序。其中,我非常赞同敏捷软件开发这个观点:在最初几乎不进行预先设计,但是一旦需求发生变化,此时作为一名追求卓越的程序员,应该从头审查整个架构设计,在此次修改中设计出能够满足日后类似修改的系统架构。下面是我在需要添加“长度”的属性时所提供的修改方案:

去掉商品信息表(Wares_info)中的haspic字段,添加商品额外属性表(Wares_ex_property)和商品额外信息表(Wares_ex_info)2个表来完成添加新属性的功能。

商品额外属性表(Wares_ex_property)

名称 类型 约束条件 说明
ex_pid int 无重复 商品额外属性标识,主键
p_name char(20) 不允许为空 额外属性名称

商品额外信息表(Wares_ex_info)

名称 类型 约束条件 说明
ex_iid int 无重复 商品额外信息标识,主键
wares_id int 不允许为空 所属商品标识,和Wares_info.wares_id关联
property_id int 不允许为空 商品额外属性标识,和Wares_ex_property.ex_pid关联
property_value char(200) 不允许为空 商品额外属性值

在商品额外属性表(Wares_ex_property)中添加2条记录:
ex_pid p_name
1 商品图片
2 商品长度

再在整个电子商务平台的后台管理功能中追加一项商品额外属性管理的功能,以后添加新的商品时出现新的属性,只需利用该功能往商品额外属性表(Wares_ex_property)中添加一条记录即可。

三、多用户及其权限管理的设计

要求:该数据库管理软件的系统管理员可以自行添加新用户,修改已有用户的权限,删除已有用户。

首先,分析用户需求,列出该数据库管理软件所有需要实现的功能;然后,根据一定的联系对这些功能进行分类,即把某类用户需使用的功能归为一类;

功能表(Function_table)

名称 类型 约束条件 说明
f_id int 无重复 功能标识,主键
f_name char(20) 不允许为空 功能名称,不允许重复
f_desc char(50) 允许为空 功能描述

 

用户组表(User_group)

名称 类型 约束条件 说明
group_id int 无重复 用户组标识,主键
group_name char(20) 不允许为空 用户组名称
group_power char(100) 不允许为空 用户组权限表,内容为功能表f_id的集合

用户表(User_table)

名称 类型 约束条件 说明
user_id int 无重复 用户标识,主键
user_name char(20) 无重复 用户名
user_pwd char(20) 不允许为空 用户密码
user_type int 不允许为空 所属用户组标识,和User_group.group_id关联

采用这种用户组的架构设计,当需要添加新用户时,只需指定新用户所属的用户组;当以后系统需要添加新功能或对旧有功能权限进行修改时,只用操作功能表和用户组表的记录,原有用户的功能即可相应随之变化。

四、简洁的批量m:n设计

碰到m:n的关系,一般都是建立3个表,m一个,n一个,m:n一个。但是,m:n有时会遇到批量处理的情况,例如到图书馆借书,一般都是允许用户同时借阅n本书,如果要求按批查询借阅记录,即列出某个用户某次借阅的所有书籍,该如何设计呢?让我们建好必须的3个表先:

书籍表(Book_table)

名称 类型 约束条件 说明
book_id int 无重复 书籍标识,主键
book_no char(20) 无重复 书籍编号
book_name char(100) 不允许为空 书籍名称
……      

借阅用户表(Renter_table)

名称 类型 约束条件 说明
renter_id int 无重复 用户标识,主键
renter_name char(20) 不允许为空 用户姓名
……      

借阅记录表(Rent_log)

名称 类型 约束条件 说明
rent_id int 无重复 借阅记录标识,主键
r_id int 不允许为空 用户标识,和Renter_table.renter_id关联
b_id int 不允许为空 书籍标识,和Book_table.book_id关联
batch_no int 不允许为空 批量借阅编号,同一批借阅的batch_no相同
rent_date datetime 不允许为空 借阅时间
……      

其中,同一次借阅的batch_no和该批第一条入库的rent_id相同。举例:假设当前最大rent_id是64,接着某用户一次借阅了3本书,则批量插入的3条借阅记录的batch_no都是65。之后另外一个用户租了一套碟,再插入出租记录的rent_id是68。采用这种设计,查询批量借阅的信息时,只需使用一条标准T_SQL的嵌套查询即可。

五、冗余数据的取舍

我原先所在的公司为了解决员工的工作餐,和附近的一家小餐馆联系,每天吃饭记账,费用按人数平摊,月底由公司现金结算,每个人每个月的工作餐费从工资中扣除。当然,每天吃饭的人员和人数都不是固定的,而且,由于每顿工作餐的所点的菜色不同,每顿的花费也不相同。例如,星期一中餐5人花费40元,晚餐2人花费20,星期二中餐6人花费36元,晚餐3人花费18元。为了方便计算每个人每个月的工作餐费,我写了一个简陋的就餐记账管理程序,数据库里有3个表:

员工表(Clerk_table)

名称 类型 约束条件 说明
clerk_id int 无重复 员工标识,主键
clerk_name char(10) 不允许为空 员工姓名

每餐总表(Eatdata1)

名称 类型 约束条件 说明
totle_id int 无重复 每餐总表标识,主键
persons char(100) 不允许为空 就餐员工的员工标识集合
eat_date datetime 不允许为空 就餐日期
eat_type char(1) 不允许为空 就餐类型,用来区分中、晚餐
totle_price money 不允许为空 每餐总花费
persons_num int 不允许为空 就餐人数

就餐计费细表(Eatdata2)

名称 类型 约束条件 说明
id int 无重复 就餐计费细表标识,主键
t_id int 不允许为空 每餐总表标识,和Eatdata1.totle_id关联
c_id int 不允许为空 员工标识标识,和Clerk_table.clerk_id关联
price money 不允许为空 每人每餐花费

其中,就餐计费细表(Eatdata2)的记录就是把每餐总表(Eatdata1)的一条记录按就餐员工平摊拆开,是个不折不扣的冗余表。当然,也可以把每餐总表(Eatdata1)的部分字段合并到就餐计费细表(Eatdata2)中,这样每餐总表(Eatdata1)就成了冗余表,不过这样所设计出来的就餐计费细表重复数据更多,相比来说还是上面的方案好些。但是,就是就餐计费细表(Eatdata2)这个冗余表,在做每月每人餐费统计的时候,大大简化了编程的复杂度,只用类似这么一条查询语句即可统计出每人每月的寄餐次数和餐费总帐:

SELECT clerk_name AS personname,COUNT(c_id) as eattimes,SUM(price) AS ptprice FROM Eatdata2 JOIN Clerk_tabsle ON (c_id=clerk_id) JOIN eatdata1 ON (totleid=tid) WHERE eat_date>=CONVERT(datetime,'"&the_date&"') AND eat_date<DATEADD(month,1,CONVERT(datetime,'"&the_date&"')) GROUP BY c_id

想象一下,如果不用这个冗余表,每次统计每人每月的餐费总帐时会多麻烦,程序效率也够呛。那么,到底什么时候可以增加一定的冗余数据呢?我认为有2个原则:

1、用户的整体需求。当用户更多的关注于,对数据库的规范记录按一定的算法进行处理后,再列出的数据。如果该算法可以直接利用后台数据库系统的内嵌函数来完成,此时可以适当的增加冗余字段,甚至冗余表来保存这些经过算法处理后的数据。要知道,对于大批量数据的查询,修改或删除,后台数据库系统的效率远远高于我们自己编写的代码。

2、简化开发的复杂度。现代软件开发,实现同样的功能,方法有很多。尽管不必要求程序员精通绝大部分的开发工具和平台,但是还是需要了解哪种方法搭配哪种开发工具的程序更简洁,效率更高一些。冗余数据的本质就是用空间换时间,尤其是目前硬件的发展远远高于软件,所以适当的冗余是可以接受的。不过我还是在最后再强调一下:不要过多的依赖平台和开发工具的特性来简化开发,这个度要是没把握好的话,后期维护升级会栽大跟头的。
参考:https://www.cnblogs.com/hoojjack/p/4705830.html

Guess you like

Origin www.cnblogs.com/zheng123/p/11334390.html