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

  可变属性的需求:我们需要在数据库里面存储很多电器,比如电视,冰箱等等。通常,在程序中,我们的类图为:

EVA设计

  对于这种继承下来的可变属性时,有一种办法是创建另外一张表,将属性当成行来存储。

  

  其中存储的数据类似下面这样:

  

  这样的设计称为:实体-属-值,简称:EVA,或者又叫开放架构、无模式。

  这种设计有如下3种好处:

  1、这两张表的列都很少。

  2、新增的属性不会对现有的表结构造成影响,不需要新增列。

  3、避免由于空值而造成的表内容混乱。

  但是这样也有如下缺点:

  1、查询属性

  本来,我们想要按出厂日期查询,只需要:

  SELECT ElectricId,DateOfManufacture FROM Electric

  但是这种方式不行,它需要这样:

  SELECT ElectricId,AttrValue AS 'DateOfManufacture'FROM AttributeWHERE AttrName = 'DateOfManufacture'

  2、无法声明强制属性

  本来,我们要确保DateOfManufacture(出厂日期)这个属性有值,在传统数据库设计中,只需要很简单的声明一个NOT NULL就OK了。

  但是现在在EVA设计中,每个属性对应的是Attribute中的一行。我们需要建立一个约束来检查对于每个ElectricId都存在一行,并且这行的AttrName是DateOfManufacture。并且这行记录的AttrValue不为空,并且符合日期格式。

  3、无法使用SQL的数据类型

  由于AttrValue的格式只能声明为Varchar或NVarchar类型,因此用户输入的日期格式可能是各种各样,甚至有的根本就不是日期格式。

  由于数据类型不能够由限制,因此我们执行如下SQL语句也不会报错。

  INSERT Attribute VALUES(1,'DateOfManufacture','我不是一个日期')  --这样的语句也不报错

  4、无法确保引用完整性

  加入上面的设计,我们需要添加一个品牌属性。可选值必须是存在的比如,三星,康佳,海尔等等。在传统的数据库设计中,我们只需要设计一张品牌表,并给本表添加一个品牌Id字段,建立外键约束就可以了。

  但是,在EVA设计中,因为品牌属性对应的是一行,因此我们无法使用外键来确保引用完整性。如果我们不处理,那么用户输入的品牌属性的值可能是不存在的。

  5、重复记录

  在EVA设计中,我们可能将同一个属性了两次。

  因为,我们连续执行如下SQL语句两次也是不报错的:

  INSERT Attribute VALUES(1,'DateOfManufacture','2013-09-09')INSERT Attribute VALUES(1,'DateOfManufacture','2013-09-10')

  由于可能存在重复记录,因此我们按出厂日期统计出厂产品数量也并不可靠。同时,按日期统计,也很复杂。

  SELECT ElcDate, COUNT(*) AS Per_Date FROM (SELECT DISTINCT ElectricId,AttrValue AS ElcDateFROM AttributeWHERE AttrName = 'DateOfManufacture')GROUP BY ElcDate

  这是Oracle中的写法。

  6、重组列

  在传统数据库设计中,加入我们要显示一条完整的记录,我们只需要:

  SELECT * FROM Electric

  但是现在,我们要:

  SELECT i.ElectricId,i1.AttrValue AS 'Name',i2.AttrValue AS 'DateOfManufacture',i3.AttrValue AS 'Screen'FROM Electric AS iLEFT OUTER JOIN Attribute AS i1 ON i.ElectricId = i1.ElectricId AND i1.AttrName='Name'LEFT OUTER JOIN Attribute AS i2 ON i.ElectricId = i2.ElectricId AND i2.AttrName='DateOfManufacture'LEFT OUTER JOIN Attribute AS i3 ON i.ElectricId = i3.ElectricId AND i3.AttrName='Screen'

  不在多说,总而言之,以上的设计,并非一个非常耐得住推敲的设计。

解决方案

  一、单表继承

  单表继承的设计是将所有相关的类型都存在一张表中,为所有类型的所有属性都保留一列。同时使用一个属性来定义每一行表示的子类型。

  例如,对于以上电器的需求,单表继承的数据设计如下:

  

  单表继承的方式可以理解为,所有子类的字段,都往单表里放,存储的时候,当某子实体没有的时候,相应的类为空,都是预留一列作为标记类型。

  单表继承的缺点就是:

  •   列过多。
  •   过多NULL值。
  •   当要增加属性的时候,要改动表结构。

  综上所述:单表继承只是适合使用子类的特殊属性列不多的情况。

  二、实体表继承

  实体表继承可以理解为:子表在设计的时候,将父表的所有的属性全部都在本表定义多一次。

  回到上面的例子,如果用实体表继承的话,对应的设计如下:

  

  实体表继承相比于单表继承,有一个好处,就是防止在一行内存储太多和当前子类型无关的属性。比如在冰箱表里没有了屏幕列,而在单表继承中,是由Scree列的NULL值的。另外,也不用在加多一个列用于标记当前是什么电器。

  实体表继承的致命缺点:

  重复列过多

  重复列过多,很容易让人摸不着头脑。

  三、类表继承

  我的推荐,我最喜欢,我认为最可靠的方式

  类表继承模拟了高级程序语言中的继承,把表当成面向对象里的类。创建一张基表,包含所有子类型的公共属性。对于每个子类型,创建一个独立的表,通过外键和基类表相连。

  对以以上例子,类表继承的设计如下:

  

  类表继承,相比于实体类继承,明显的有点在于,少了很多重复列。子类表中,主键同时也是外键。

  我认为这是一个比较好的方法。

  四、半结构化

  半结构化,实际上跟单表继承差不多。单表继承是多个列,而半结构化使用一个新特性,比如一个xml类型的列,来存储子类的属性。

  对于以上例子,半结构化的设计如下:

  

  子类的信息,存在一个XML列中,你爱设置什么节点就什么节点。反正查询起来也不麻烦。不够要记住的是,要有一个Type列,来标记哪行是哪种电器。不然就全乱套了。

  由于,现在SQLServer对XML的支持越来越强大,这也是一个不错的选择。

分类: 数据库设计:SQL反模式笔记
绿色通道: 好文要顶 关注我 收藏该文与我联系

逆心
关注 - 28
粉丝 - 631

+加关注

2
0
(请您对文章做出评价)

« 上一篇:NHibernate使用MemCache二级缓存
» 下一篇:逻辑数据库设计 - 多态关联

posted on 2015-07-17 17:14 铭轩同学 阅读(...) 评论(...) 编辑 收藏

转载于:https://www.cnblogs.com/mingxuantongxue/p/4655166.html

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

  1. 《教妹学数据库系统》(五)逻辑数据库设计(上)

    hello大家好,今天我们来学习逻辑数据库设计.教妹学数据库,没见过这么酷炫的标题吧?"语不惊人死不休",没错,标题就是这么酷炫. 我的妹妹小埋18岁,校园中女神一般的存在,成绩优 ...

  2. 逻辑数据库设计 - 单纯的树(邻接表、路径枚举、嵌套集、闭包表)(引)

    相信有过开发经验的朋友都曾碰到过这样一个需求.假设你正在为一个新闻网站开发一个评论功能,读者可以评论原文甚至相互回复. 这个需求并不简单,相互回复会导致无限多的分支,无限多的祖先-后代关系.这是一种典 ...

  3. 数据库设计方法论 - 继承

    继承这个概念做java开发的同学应该都很熟悉了,继承指的是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为. 数据库设计的时候也是 ...

  4. 数据库设计中的英文术语表

    Access method(访问方法):此步骤包括从文件中存储和检索记录. Alias(别名):某属性的另一个名字.在SQL中,可以用别名替换表名. Alternate keys(备用键,ER/关系模 ...

  5. 数据库设计系列9--将ER模型映射为表

    在前面的步骤中,我们创建了数据库的ER模型,ER模型属于概念级别的模型,需要映射为表才能被计算机存储.本章节的目标就是从ER模型中创建表,并检查这些表的结构.这组表应该代表逻辑数据库模型中的实体,关系 ...

  6. 数据库 设计中的英文术语

    2019独角兽企业重金招聘Python工程师标准>>> Access method(访问方法):  此步骤包括从文件中存储和检索记载. Alias(别名):  某属性的另一个名字.在 ...

  7. MySQL数据库 第4章:数据库设计

    MySQL数据库 第4章:数据库设计 4.1 数据库设计概述 4.2 数据库设计范式 4.3 数据建模工具 4.4 数据库设计-电子商务网站 4.4.1 需求分析 4.4.2 准备工作 4.4.3 商 ...

  8. 《数据库系统》(六)物理数据库设计

    hello大家好,上次学习了逻辑数据库设计(点击查看),今天我们来学习物理数据库设计.教妹学数据库,没见过这么酷炫的标题吧?"语不惊人死不休",没错,标题就是这么酷炫. 我的妹妹小 ...

  9. 网站评论功能数据库设计和开发

    本文主要分享了我在设计评论模块中的一些心得,希望对读者有些许帮助. 需求分析 现阶段评论做的最好的我想应该是网易新闻(app)里面的评论模块了,其"盖楼"的方式让人印象深刻,评论已 ...

  10. 目录树结构的数据库设计思考

    昨天一同事遇到一问题,找我帮忙解决一下,他的需求是这样的,服务器将收集好的数据返回回来,客户端要解析并展现成树状的,类似于QQ客户端那样,大概就如下面这张图,这是他们网页端实现的界面. 其实需求挺简单 ...

最新文章

  1. 算法炒房三月亏20多亿!房地产巨头大翻车!
  2. Linux下编译安装Apache、php和svn
  3. html中::before 爬虫_反反爬虫系列(四)
  4. 性能优化-Bitmap内存管理及优化
  5. ntfs 格式在linux下挂载
  6. Android SDK Manager 加载不出tools解决办法
  7. 深入浅出CSS(二):关于雪碧图、background-position与steps函数的三角恋情
  8. php super和parent,parent()、parents()的用法区别
  9. JAVA学习-数组元素排序
  10. 导出zabbix的IT service报表
  11. jstack简单使用,定位死循环、线程阻塞、死锁等问题
  12. Linux文件查找及压缩工具
  13. i.MX 8M Mini sai_low_power_audio
  14. x86_64-w64-mingw32/bin/ld.exe: cannot find -lmsvcrt
  15. 河北省计算机专业对口大学分数线,计算机对口升学河北分数线2017
  16. 程序员编程中遇到的那些灵异事件,胆小误入!
  17. 百度api文字转语音效果
  18. python学多久可以接单-详解 | Python学多久才能独立接单赚钱?一个月足够了!
  19. Android:修改默认音量等级
  20. 【数据结构】无向图与有向图的连通性及相关算法

热门文章

  1. 怎样在图片上编辑文字?这几种方法可以进行简单的编辑
  2. python3中expected an indented block(缩进问题)
  3. Vue + Element-UI —— 项目实战(一)
  4. [Telink][TLSR8251] [泰凌微]入门上手教程(IDE+SDK+烧录)
  5. redis读缓存超时故障处理
  6. f2fs系列文章gc
  7. [haoi2009]毛毛虫 树形dp
  8. SpringBoot项目实现网络测速功能
  9. Material design - 色彩样式(一)
  10. 微信小微商户申请入驻接口PHP示例