高质量数据库建模系列课程<4> PPT & 讲义 - 属性 & 域

浏览: 3604

广告:

欢迎参加我的课程:高质量数据库建模



大家好, 先给大家拜个晚年。

上一节课我们讲完了实体,以及实体的分类,这一节课让我们来看看什么是属性。

这里给了一个样例图:

实体名呢,是:员工

那么有了员工这个实体,我们还需要一些属于员工所具备的特性的内容来详细的描述员工。

比如,员工的ID,员工的姓名,员工的年龄这些信息。

而这些,就是员工这个实体的属性。

 

实体对应于数据库中的表,而属性对应于数据库中表的列。

在关系型数据库建模中,属性都是单值的,如果有多值的情况,就需要建另外的属性表,也就是我们上一节课程中描述的属性表的Pattern。

 

属性的内容也非常广泛,和实体一样,我们也尝试按内容对他们进行分类,下面尽可能的罗列了一些分类,而实际的应用远远不止于此。

再强调一次,无论是对实体,还是对属性,我们这种的分类的方式都是为了帮你梳理模型的内容,启发你填充信息,并且帮你有条理的检查是否有遗漏。这里是介绍一种方法,在实际的项目中呢,你可以根据实际的数据情况进行类似的分类。

 

第一类属性:ID

这种是最常见的,几乎所有强实体都有。就是用于标识实体唯一性的属性,一般都是主键。

通常有很多种存在的方式,比如身份证号码,学号之类的。

 

第二类属性:描述

最典型的,名字,还有各种描述,可以分为短描述,长描述,还有备注之类的信息。

 

第三类属性:引用

这个一般都是引用其他实体的属性,比如订单实体,里面就要引用客户的信息,商品的信息,所以要在订单实体里面要加客户的ID,商品的ID

 

第四类属性:分类

这种也非常常见,就是为了方便管理,需要将实体分门别类。比如方便面,可以按形状分类:杯碗桶袋,也可以按口味分:红烧牛肉,海鲜虾仁,老坛酸菜,还有各种各样的分类方式。

 

第五类属性:限制

比如服装店卖东西,是可以讨价还价的,然后呢,总部给下面的销售员的限制是:最低不能低于7折,之类的。

 

第六类属性:数量

这个很广义了,所有和数字沾边的都可以算,比如订单中购买商品的数量,购买商品的金额等等。

 

第七类属性:时间相关

这个和我们前面提到的5W1H差不多,指的是when,内容太多了,比如交易日期,发货日期,登陆时间,注销时间,等等。

 

第八类属性:人物相关

这个指的是who,比如假设实体为公司,那么这个实体就需要包含企业联系人信息,法人信息等等。

 

第九类属性:地点相关

就是Where, 比如交易发生的地点,登陆用户的IP地址,等等。

 

第十类属性:状态

比如,对于一个员工有多种状态,比如在职,退休,离职,停薪留职,之类。

 

第十一类属性:审计

这种也非常常用,尤其数据仓库里面,最常见的时间戳,insert timestamp, update timestamp,操作人,谁操作的数据,还有什么?数据从哪来的,source system id。

 

第十二类属性:派生

为了方便程序的实现,比如提高性能做的预计算等等。比如我已经有本期数据了,然后我想要本年累计数据,为了后面查询功能省事,这个我就给可以事先算出来。还有CHECKSUM Code,比如为了知道几十个字段是否发生变化了,我会MD5的算法,自动生成CRC校验码,这是为了方便后面ETL程序使用。

 

如上十二类的属性,说实话就是我随便敲出来的,还有更多更多的属性分类并没有包含进来,在这里我提供这种分类的目的是什么?主要目的是为了让建模工程师能够条理清晰的思考问题,以便与用户进行沟通。并且呢,能够帮助我们review模型的质量,减少遗漏。另外的功能是能够帮助标准化,统一化。对于比如审计这种类型属性,我们还可以做成标准化的Pattern,在每个实体中都能增加insert timestamp, updatetimestamp, checksum code, operator,current indicator之类的属性。


按照属性的内容分类之后呢,属性还有一些其本身具有的自然特性,而这些特性中呢,有的需要作为模型的描述内容记录下来,还有一些需要在数据库层有所体现。

在建模过程中,当我们创建某一属性时,可以问自己,问客户,如下问题,让我们一步一步完成模型的建立、

 

第一,属性是强制的还是可选的。

表示,某一属性,是否可为空,如果是强制的,那么一定不能为空,如果是可选,则可以为空。这一特性是需要应用到数据库中的。

比如,员工编号,员工电子邮箱,这种类型的属性强制不可为空。而员工的兴趣爱好等信息,则可以设置为空。

 

第二,属性是原子还是组合?是直接的还是派生的?

比如:员工的姓,员工的名都是原子的,而员工的全名,是由姓+ 名来构成的,这种属性就是组合的属性。而有些数据库呢是能够提供这种计算项功能的。

 

第三,属性是单值的还是多值的?

比如前面我们说过的例子,客户的地址,可能有好几个,这种属性呢就是多值属性。而在关系型数据库里面,是不支持在单实体中存在多值属性的,如果遵从3NF,就需要拆分出去建表。

 

第四,属性是否为可选键

可选键的含义是,某个属性,或某几个属性的组合,能够作为该实体的标识,也就是能够唯一确定实体的一个实例。举个例子,员工的编号, 员工的email地址都是员工这个实体的可选键。

 

第五, 属性的数据类型

确定完属性的自然特性以后,我们需要对属性的取值进行进一步的定义。属性取值很多了,包括我们最常用的整形啊,浮点型,字符型,等等,内容非常丰富。

 

第六, 属性是否有默认值

指的是当新增一条记录时, 如果不为属性指定任何数值, 是否需要有缺省的确定. 比如,对于审计类的属性,insert timestamp, 我们可以设置成current timestamp, 当插入一条数据时,用当前的系统时间作为其缺省值。默认值对于数据质量管理是很重要的,我们在数据模型构筑的时候不要忽略。

 

第七,派生属性是如何计算的

对于一些派生属性,比如员工的全名,采用姓+ 名。在设计逻辑模型时我们需要对其加以注释,有些属性可以在某些特定的数据库中直接按照计算项模式计算出来。对于无法直接计算的,我们在设计时也需要列出计算逻辑,以便于未来做程序的人员方便实现。

 


如前面介绍的,属性的数据范围内容很多,包括整形,浮点,布尔,字符等等很多类型,这里我列了一个长长的列表,大家如果感兴趣可以课后自行学习,在这里我就不一一介绍了,这里提示一点,这个属性的数据范围和最终你要使用的数据库息息相关,主要在逻辑模型设计阶段不要选择超出数据库所能够支持的数据类型范围。这里的列表呢,都是数据库初始定义的数据类型,而在数据模型设计中呢,我们还可以自定义数据类型。


 

数据库的自定义数据类型称为域,也就是Domain。

域是指属性的所有取值范围的集合,其实也就是为可增加约束的自定义数据类型。

 

这个我们需要讲一下,自定义域,在我们日常的数据库设计中用到的是很少的,而我发现在很多知名Package类型的软件,比如SAP之类的产品,用的就很多。但是其实它对于数据质量,数据规范,数据标准化等是很有用的。

一个域是一组符合一定规范条件的数据集合,一个域可以使用在多个属性中。举几个例子,比如性别,一般就是两种Male和Female,当然也有可能有未知的,定义成Unknown,也就是说最多3种情况,输入的数据不能超出这范围。此外域也和具体场景紧密相关,比如像货币,我们可以定义一个域叫Currency,对于大部分公司而言如果定义成Numeric(15,2),也就是说到千亿级别,保留小数点两位。基本上就能代表绝大多数的货币范围,但是对于一些巨型规模的金融公司,这个范围可能就不够了。

 

域有三种不同的类型,

 

第一种是格式,我们自定义的格式的域,就比如我前面举的货币的例子,就是采用numeric(15,2)的数据格式。还有像Email地址,这种中间会有@的字符串模式,再有就是像身份证号这种18位长的字符串模式,等等。

 

第二种是列表,这个是典型的枚举类型。对于这种模式的域,通常列表的内容比较稳定,而且数据也不宜过多。比如前面举例的性别,还有星期,月份这种。都可以以列表域的方式定义。

 

第三种是范围,这个比如我可以限制一个员工的年龄是0岁到150岁之间,之类。

 

 那么使用域有哪些好处呢?

 

首先, 提高数据质量。

通过域的定义,去建立用于检验数据合法性的规则,去避免非法数据的插入。这个其实就是在数据库层面而不是在应用层面去规范数据质量。

 

比如我们前面提到的,性别,这个就是属于列表模式的属性,只有Male,Female和Unknown可以插入(这里呢我们用M代表Male,F代表Female,U代表Unknown)。这样这三个以外的数据就不允许插入进来,就是通过这种办法去保证数据质量。

 

其次,使数据模型更容易理解,以及方便沟通

比如,我们可以自定义域为currency,这样可以把诸如销售金额(sales_amount), 产品成本(product_cost)等等这类和钱相关的字段都设置为currency。使用数据模型的人就更容易理解字段的含义。再比如,对于列表类的域,在定义域的时候就把枚举的内容填充进去了,使用者能很方便的通过域的定义(也就是枚举的内容)去了解对应字段的含义。

还有,使数据字段管理标准化,也更方便元数据管理的中心化实现。比如,在整个应用,乃至整个企业都使用标准域的定义,这样在系统A中使用的域定义,也可以重用到系统B中,提高整体的开发效率。并且还能保持数据类型的一致性。比如系统A中所有钱相关的字段用currency定义。系统B就可以直接使用currency这个domain,也就会和A系统中保持一致了。再举个例子,比如系统设计的时候可能会有很多名字,像人名,公司名,部门名等等,我们创建两个域, 一个叫shortname用varchar(50),一个叫longname用varchar(255),这样如果人名,部门名这种明显比较短的,shortname能够容纳下的字段,我们就用shortname作为domain,公司全名这种长的,我们就用longname作为domain。 这样以这个为标准,同一个系统里面的各个字段,甚至所有系统都用这种统一的标准,就会很少发生同一含义的数据在不同系统不同表数据长度定义不同的问题。Data type inconsistent这种问题,实际上是非常常见的,我们在整理数据质量问题的时候就经常发现,同一个字段,在不同表中的定义长度还有不同,这就带来了很多隐患,比如某些长度定义不够,字符串被截断这类问题。

 

这里说了一堆域的好处,那域的定义有没有什么缺点或者隐患啊?其实啊,域的定义也是双刃剑,带来好处的同时,也会带来一些风险。

这里举个例子,比如我用shortname作为公用的domain,员工的名字用shortname这个domain的定义,我定义的varchar(50), 但就有一些特别的员工,他们的名字varchar(50)盛不下,比如巴西的员工,他们的名字都N长,我曾经见识过一共86个字母的员工名字。那我怎么办啊?有一个办法是,我把shortname的定义给改了,改成varchar(100),这样因为系统里面所有员工姓名相关的字段都还是用shortname这个域定义的,所以这个就是域的好处,我直接改了域的定义,就不用每个字段每个字段去调整长度了,这就提高了效率。但这么做其实也有坏处,比如其他用到shortname的字段,像部门名这种的,也受到牵连,本来其实他们是不用改的,varchar(50)就够了。改成varchar(100)以后呢,会浪费存储空间,并且如果表太宽,原有的tablespace装不下,还得改表结构。

那不用这个办法呢?我就得重新定义一个新的域去处理这种特殊的情况。比如建一个shortname2的域,定义成varchar(100), 然后把员工姓名相关的字段的定义都改成shortname2。这种呢,假如这种例外越来越多,就会增加很多域管理方面的麻烦。如果我们在域上面增加了check这种功能,可能这种特例的数据会更多,也就是说会带来更多管理方面的风险。

 

所以域的定义要很小心,对于未来的数据变化,以及例外数据的考虑的充分一些。当然,也不能因噎废食,只要我们管理的好,域就会很有用途。

 

今天的课和前面不太一样,有些朋友在学过本课以后,提了一些建议,说理论太多实操太少,那么从这节课开始呢, 我会增加一些实操的内容, 主要是配合讲解的内容,在数据库中的一些操作以及CASE工具的使用. 前面我们讲了很多关于CASE工具的好处, CASE工具有几个很有名的,比如CA公司的ERWIN, IBM的InfosphereData Architect, SAP的Sybase PowerDesigner这几个都是收费的,还有一个免费的Oracle的SQL Developer Modeler。从前我在群里做过一个调查,大家好像还是更希望用PowerDesigner来讲, 我IBM的IDA用的最熟,PowerDesigner其实很少用, 但为了遵从大家的建议,我也尝试去用PowerDesigner去讲解,同时呢和大家共同学习。那今天我们讲的例子就是用PowerDesigner去创建域,以及创建对应的表。这里呢,本来我想用MySQL去作为实操练习的数据库,不过我发现MySQL不支持域,虽然它也有枚举的数据类型,但功能上还是有所欠缺,其他的主流数据库,比如Oracle,MS SQL Server, DB2什么的都支持域, 但考虑到软件License的问题,这里我们选另外一个著名的开源数据库PostgreSQL。

 

首先呢, 让我们先看看在数据库层是怎么怎么适用域的。这里我有准备好的脚本。

 

首先我们要创建两个域,一个是AGE, 一个是GENDER性别。其中呢,对于AGE这个域,我们把它定义成short integer,然后范围设定为0-150,不在这个范围内的就不是合法数据。DDL是这么写的:

CREATEDOMAIN AGE AS INT2

CHECK(VALUE>0 and VALUE<150)

;

对于性别,我们设置成char(1),只有三个枚举值,M:Male, F: Female, U:Unknown。DDL是这样的:

CREATEDOMAIN GENDER AS CHAR(1)

CHECK(VALUE in ('M','F','U'))

;

创建完这两个域以后,我们创建一个员工表,EMPLOYEE, 有四个字段,DDL是这样的:

我们可以看到前两个column,都是用的数据库原有的数据类型,后面两个column, EMP_AGE用的就是我们新定义的域AGE,EMP_GENDER用的域GENDER。

然后我们尝试插入三条数据,第一条数据是正常的,第二条数据的EMP_AGE不在范围内,第三条数据的EMP_GENDER不在范围内,我们可以看到,第一条能正常插入,后面两条插入失败,这也就是我前面提到的,使用域,可以有效的控制数据质量。

 

这里我再讲一个域的用法,也就是借助PowerDesigner。PowerDesigner有个功能,你可以在Model里面定义域,它能够帮你建立标准化的数据类型,以及constrain。而在真实的数据库中里面,你可以不用建域而能达到域类似的功能。顺便我也讲一下PowerDesigner里面如何创建逻辑模型,如何从逻辑模型转换到物理模型,如何使用域以及怎么生成DDL。

我手里的版本是PowerDesigner 16.5。


/*

ooooh,可惜,录制操作这部分我并没有写脚本,是在现场讲的,大家还是去视频里面听吧,不好意思了。

附件中是实操例子中的SQL文件以及PowerDesigner的LDM和PDM文件,请参考。

*/

推荐 9
本文由 BAO胖子 创作,采用 知识共享署名-相同方式共享 3.0 中国大陆许可协议 进行许可。
转载、引用前需联系作者,并署名作者且注明文章出处。
本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责。本站是一个个人学习交流的平台,并不用于任何商业目的,如果有任何问题,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

3 个评论

谢谢胖子老师,这些详细的笔记。
谢谢老师的分享
谢谢老师,这么好的文章和视频 要大力推广

要回复文章请先登录注册