数据库设计之EAV(实体、属性、值)

有这么一个业务,用于客户记录每天做的事情,由于是非常专业的事情,需要专业的记录本,这种记录本有20多种。实际工作中也是有20多样的记录本,记录本的格式每隔一年会有点变动。如何进行数据库设计?

   有两种方案:

1.为每个记录本建单独的表。

2.动态表,把记录本的属性放入到字典中,记录本的内容以实体、属性、值的形式存储。

   --存储记录本的格式

createtable note_dictionary

(

dictionary_id
number,

dictionary_type
varchar2(50),--记录本的类型,就是那20多种记录本

dictionary_name
varchar2(200)--记录本中的名称

);

   --存储记录本的内容

createtable note_content

(

content_id
number,

note_id number,
--具体的一个记录本的id

dictionary_id
number,--记录本中字段的id

content
varchar2(1000)--字段的内容

);

如果只是从开发人员的角度来看,会选择方案2。方案1工作量多大啊,每次改记录本的格式都要做调整,方案2都有扩展型啊,调整格式都不需要改代码。毫无争议的选择方案2。

选择方案2后,会牺牲很多传统数据库设计代码的好处,如果记录本之前是有关系的,实现会变得更复杂。

1.记录本中的字段类型无法制定,如果是Date和number,只能用varchar2表示。关于类型选择不正确会造成什么问题,在我之前的blog中有写到。再者统计也可能出现问题,即使你前段控制的再好,也不能保证最后到数据库中后的是正确的,这个问题看到的太多了。

2.不能加not null的约束和默认值。

3.如果要查某个记录本的a字段,需要先去找字典,然后再到内容表中去找,不直观,涉及到后期维护数据较麻烦。

4.如果记录本之间是有关系,要建立关联关系,需要再加表,实现很复杂。

5.在一段时间后内容表会变得非常之笨重,系统中就属它数据量大。

6.我以前维护过这种设计代码,因为是通用的,有时候改了这里,也不知道会不会影响其他的地方。Java代码中使用了反射,debug很难调试,问题难定位。总体来说,有一种身不如死的感觉。

上面的模块我倾向选择方案1,开发工作量大一点,但维护工作量小,数据更加精准。那是不是一定不要用方案2呢?也不是,业务,业务,还是业务,如果你的单据不需要统计分析,数据量也不大,单据种类非常多,开发人员水平很高,你想要做到记录本可配置,那可以选择方案2。如果你不详细了解业务的情况下,坚持选择方案2,你必须承担我上述说的风险。

时间: 2024-10-14 00:58:21

数据库设计之EAV(实体、属性、值)的相关文章

SQL反模式学习笔记6 支持可变属性【实体-属性-值】

2014-10-11 17:21:31 目标:支持可变属性 反模式:使用泛型属性表.这种设计成为实体-属性-值(EAV),也可叫做开放架构.名-值对. 优点:通过增加一张额外的表,可以有以下好处 (1)表中的列很少: (2)新增属性时,不需要新增列.不会影响现有表的结构: (3)存储的字段内容不会为空值. 缺点:(1)查询语句变得更加复杂: (2)使用EAV设计后,需要放弃传统的数据库设计所带来的方便之处,比如:无法保障数据完整性: (3)无法使用SQL的数据类型,比如对日期.金钱等格式内容都只

逻辑数据库设计 - 可变属性(继承)

可变属性的需求:我们需要在数据库里面存储很多电器,比如电视,冰箱等等.通常,在程序中,我们的类图为: EVA设计 对于这种继承下来的可变属性时,有一种办法是创建另外一张表,将属性当成行来存储. 其中存储的数据类似下面这样: 这样的设计称为:实体-属-值,简称:EVA,或者又叫开放架构.无模式. 这种设计有如下3种好处: 1.这两张表的列都很少. 2.新增的属性不会对现有的表结构造成影响,不需要新增列. 3.避免由于空值而造成的表内容混乱. 但是这样也有如下缺点: 1.查询属性 本来,我们想要按出

数据库设计之存储多值的问题

存储多值的问题在设计数据库时是很普遍的问题,看到很多开发人员在上面吃了亏,我觉得有必要拿出来说. 业务场景:一个业务单据,有多个联系人.一个设备维护工作,有多个维护班组.下面来举个例子 createtable BILL ( bill_id numberprimarykey, bill_name varchar2(20), bill_contentvarchar2(200), contact_idnumber--来至于user表的user_id ); 1. 在起初的设计中,联系人只有一个,后来需求

数据建模和数据库设计

http://blog.csdn.net/suwu150/article/details/52724937 数据建模和数据库设计       一.    实体-关系图        实体-关系图(Entity Relationship Diagram),也称为E-R图,提供了表示实体.属性和关系的方法,用来描述现实世界的概念模型.        构成E-R图的基本要素是实体.属性和关系        实体(Entity):实体用来表示具有相同特征和性质的事物(类似于java的类),实体由实体名和

数据库设计的必要性

为什么要对数据库进行设计? 当我们要存储的数据比较少的是后当然不需要对数据库进行设计,但是当我们对数据的需求量越来越大时对数据库的设计就很有必要性了!如果数据库的设计不当会造成数据冗余.修改复杂.操作数据异常等问题而好的数据库设计则可以减少不必要的数据冗余,通过合理的数据规划提高系统的性能! 什么是数据库设计? 数据库设计就是将实体与实体之间的关系进行规划和结构化的过程 设计数据库的步骤 1.现实世界业务需求------->绘制E-R图--------->绘制数据库模型图-----------

逻辑数据库设计 - 多态关联

多态关联 先说明什么是多态关联. 假设我们有一张地址表,其中的地址可能是对于User中的,也可能是对于Orders中的. 以上,只是举个例子,实际的例子还有很多,比如我们要设计一个内容管理系统(CMS),我们的CMS有一个文章表,一个软件表.还要求支持评论,那么我们的评论表的Id是引用文章表还是引用软件表呢? 对于以上例子的缺点,貌似书本上有故意为此多态关联的模式走软的嫌疑.缺点不说了,主要是查询麻烦,其次不能够支持外键约束. 解决方案 交叉表 对于这种需要外键引用为多个表的情况,可以建立一张交

java利用映射表名称反射创建实体类并赋属性值

1.hibernate中首先进行初始化,将对应的表名和类名以键值对的方式存放到map中 private Map<String, String> mappings;//全局变量 /** * 根据数据库表名获取实体类 */ public void initMappings() { if (mappings == null) { mappings = new HashMap<String, String>(); SessionFactory factory = this.getSessi

Java实体Date类型属性值无法保存到数据表对应字段的问题

项目框架: maven+springMVC+mybatis 实体属性: //推荐时间private java.util.Date recommendDate; 数据库字段: ALTER TABLE `resource`ADD COLUMN `RECOMMEND_DATE`  date NULL COMMENT '推荐时间'; 属性赋值: resource.setRecommendDate(DateUtils.getNowDate()); 相关方法: 获取现在时间 /** * 获取现在时间 * *

中小型商城系统中的分类/产品属性/扩展属性的数据库设计

声明:之所以定位在"中小型"商城系统,而非“大型”(指淘宝.拍拍这类巨无霸),理由很简单----我一直都呆在(创业型的)小公司,没见过这些大家伙是怎么设计的:) 正文: 之前发表过一篇"商城系统中[商品扩展属性]的表单生成及客户端验证",部分童鞋对于后台数据库的设计比较感兴趣,于是今天把这部分也补上. 一.产品分类设计越来越多的商城系统都热衷于选择“无限级分类”的设计,我也不例外,因为它方便扩展.这部分就不详细展开了,详见 无限级分类(非递归算法/存储过程版/GUI