2、智能健与非智能键

  智能键——键值包含额外信息,其根据某种约定好的编码规范进行编码,从键值本身可以获取某些信息;非智能键,单纯的无意义键值,如自增的数字或GUID。

  智能键是一把双刃剑,开发人员偏爱这种包含信息的键值,程序盼望着其中潜在的数据;数据库管理员或者设计者则讨厌这种智能键,原因也是很显然的,智能键对数据库是潜在的风险。前面提到,数据库设计的原则之一是不要把具有独立意义的值的组合实现到一个单一的列中,应该使用多个独立的列。数据库设计者,更希望开发人员通过拼接多个列来得到智能键,即以复合主键的形式给开发人员使用,而不是将一个列的值分解后使用。开发人员应该接受这种数据库设计,但是很多开发者却想不明白两者的优略。笔者认为,使用单一列实现智能键存在这样一个风险,是我们可能在设计阶段无法预期到编码规则可能会在后期发生变化。比如,构成智能键的局部键的值用完而引起规则变化或者长度变化,这种编码规则的变化对于程序的有效性验证与智能键解析是破坏性的,这是系统运维人员不希望看到的。所以笔者建议如果需要智能键,请在业务逻辑层封装(使用只读属性),不要再持久化层实现,以避免上述问题。

  (七)是否允许NULL

  关于NULL我们需要了解它的几个特性:

  ● 任何值和NULL拼接后都为NULL。

  ● 所有与NULL进行的数学操作都返回NULL。

  ● 引入NULL后,逻辑不易处理。

  那么我们是否应该允许列为空呢?笔者认为这个问题的答案受到我们的开发语言的影响。以C#为例,因为引入了可空类型来处理数据库值类型为NULL的情形,所以是否允许为空对开发者来说意义并不大。但有一点必须注意,是验证非空必须要在程序集进行处理,而不该依赖于DBMS的非空约束,必须确保完整数据(所有必须的属性均被赋值)到达DB(所谓的“安全区”,我们必须定义在多层系统中那些区域得到的数据是安全而纯净的)。

  (八)属性切割

  一种错误想法是,属性与列是1:1的关系。对于开发者,我们公开属性而非字段。举个例子来说,对于实体“员工”有“名字”这一属性,“名字”可以再被分解为“姓”和“名”,对于开发人员来说,显然第二种数据结构更受青睐(“姓” 和“名”作为两个字段)。所以,在设计时我们也应该根据需要考虑是否切割属性。

  (九)规范化——范式

  当笔者还在大学时,范式是学习关系型数据库时头疼的问题。我想也许会有读者仍然不理解范式的价值,简单来说——范式将帮助我们来保证数据的有效性和完整性。规范化的目的如下:

  ● 消灭重复数据。

  ● 避免编写不必要的,用来使重复数据同步的代码。

  ● 保持表的瘦身,以及减从一张表中读取数据时需要进行的读操作数量。

  ● 大化聚集索引的使用,从而可以进行更优化的数据访问和联结。

  ● 减少每张表使用的索引数量,因为维护索引的成本很高。

  规范化旨在——挑出复杂的实体,从中抽取出简单的实体。这个过程一直持续下去,直到数据库中每个表都只代表一件事物,并且表中每个描述的都是这件事物为止。

  1、规范化实体和属性(去除冗余)

  1NF:每个属性都只应表示一个单一的值,而非多个值。

  需要考虑几点:

  ● 属性是原子性的 需要考虑熟悉是否分解的足够彻底,使得每个属性都表示一个单一的值。(和“(三)列意味着的值”描述的原则相同。)分解原则为——当你需要分开处理每个部分时才分解值,并且分解到足够用行。(即使当前不需要彻底分解属性,也应该考虑未来可能的需求变更。)

  ● 属性的所有实例必须包含相同数量的值 实体有固定数量的属性(表有固定数量的列)。设计实体时,要让每个属性只有固定数量的值与其相关联。

  ● 实体中出现的所有实体类型都必须不同

  当前设计不符合1NF的“臭味”:

  ● 包含分隔符类字符的字符串数据。

  ● 名字尾端有数字的属性。

  ● 没有定义键或键定义不好的表。