三、设计原则
(一)降低对数据库功能的依赖
功能应该由程序实现,而非DB实现。原因在于,如果功能由DB实现时,一旦更换的DBMS不如之前的系统强大,不能实现某些功能,这时我们将不得不去修改代码。所以,为了杜绝此类情况的发生,功能应该有程序实现,数据库仅仅负责数据的存储,以达到最低的耦合。
(二)定义实体关系的原则
当定义一个实体与其他实体之间的关系时,需要考量如下:
● 牵涉到的实体:识别出关系所涉及的所有实体。
● 所有权:考虑一个实体“拥有”另一个实体的情况。
● 基数:考量一个实体的实例和另一个实体实例关联的数量。
关系与表数量
● 描述1:1关系最少需要1张表。
● 描述1:n关系最少需要2张表。
● 描述n:n关系最少需要3张表。
(三)列意味着唯一的值
如果表示坐标(0,0),应该使用两列表示,而不是将“0,0”放在1个列中。
(四)列的顺序
列的顺序对于表来说无关紧要,但是从习惯上来说,采用“主键+外键+实体数据+非实体数据”这样的顺序对列进行排序显然能得到比较好的可读性。
(五)定义主键和外键
数据表必须定义主键和外键(如果有外键)。定义主键和外键不仅是RDBMS的要求,同时也是开发的要求。几乎所有的代码生成器都需要这些信息来生成常用方法的代码(包括SQL文和引用),所以,定义主键和外键在开发阶段是必须的。之所以说在开发阶段是必须的是因为,有不少团队出于性能考虑会在进行大量测试后,在保证参照完整性不会出现大的缺陷后,会删除掉DB的所有外键,以达到最优性能。笔者认为,在性能没有出现问题时应该保留外键,而即便性能真的出现问题,也应该对SQL文进行优化,而非放弃外键约束。
(六)选择键
1、人工键与自然键
人工健——实体的非自然属性,根据需要由人强加的,如GUID,其对实体毫无意义;自然健——实体的自然属性,如身份证编号。
人工键的好处:
● 键值永远不变
● 永远是单列存储
人工键的缺点:
● 因为人工键是没有实际意义的唯一值,所以不能通过人工键来避免重复行。
笔者建议全部使用人工键。原因如下:
● 在设计阶段我们无法预测到代码真正需要的值,所以干脆放弃猜测键,而使用人工键。
● 人工键复杂处理实体关系,而不负责任何属性描述,这样的设计使得实体关系与实体内容得到高度解耦,这样做的设计思路更加清晰。
笔者的另一个建议是——每张表都需要有一个对用户而言有意义的自然键,在特殊情况下也许找不到这样一个项,此时可以使用复合键。这个键我在程序中并不会使用其作为唯一标识,但是却可以在对数据库直接进行查询时使用。
使用人工键的另一根弊端,主要源自对查询性能的考量,因此选择人工键的形式(列的类型)很重要:
● 自增值类型 由于类型轻巧查询效率更好,但取值有限。
● GUID 查询效率不如值类型,但是取值无限,且对开发人员更加亲切。