话说小k现在要用数据库做一个实际的项目了,所以就准备先复习一下数据库的基础知识。小k搜集了一些资料,包括书籍和网络资料。
1.第一范式常见提法
小k发现各种资料中对第一范式常见的解释可以归结为:“第一范式(1NF)是指数据库表的每一列都是不可分割的基本数据项,同一列中不能有多个值,即实体中的某个属性不能有多个值或者不能有重复的属性。”
小k似有一些明白,又有一些不明就里。什么是“同一列不能有多个值”?什么是“不能有重复的属性”?
小k也看到了一些例子:
例:如职工号,姓名,电话号码组成一个表(一个人可能有一个办公室电话 和一个家里电话号码) 规范成为1NF有三种方法:
一是重复存储职工号和姓名。这样,关键字只能是电话号码。
二是职工号为关键字,电话号码分为单位电话和住宅电话两个属性
三是职工号为关键字,但强制每条记录只能有一个电话号码。
以上三个方法,第一种方法最不可取,按实际情况选取后两种情况。
看到这里,小k仿佛记起了第一范式的一些东西。小k总结了第一范式的定义更通俗易懂的(从数据的角度,而非模式的角度)说法:第一范式就是每一行记录的任意属性都不会包含多条(也就是上述例子中表中一行的电话号码列不会有2条);或者说不包含嵌套记录(小k杜撰的名词,需要一些微妙的感觉就不难理解)。
2.我的理解
小k原本以为大功告成,1NF就是这样了。可是当看到一个实际应用时,就抓耳挠腮了。
小k不想仅仅横向地罗列理论,若从纵向来看,这就要从数据库设计的流程说起了。一般来说我们从需求分析中获取业务流程,从中提取数据库表需要的属性。例如下图所示的订单:
从上图中可以提取所有的属性:订单ID、日期、顾客ID、姓名、地址...商品ID、描述、单价、数量、总价、合计。
小k觉得没有可拆分的属性了,难道这就已经满足第一范式了?从小k自己的定义中可以看出,商品列表(即Item ID,Item Description,Item Price,Item Quantity和Item Total Price)明显包含了多条。但是,还是和第一个例子有所不同,因为第一个例子只是有一列会有多条,这个例子则是有多列会有多条。若第一个例子看作一维的嵌套,则此例子就是二维的嵌套。(这些也是小k杜撰的)
如果按如下方案建表,则满足第一范式:
Order(Order #, Order Date, Customer ID, Customer Name, Customer Address, Customer City, State, Zip, Order Total),其中Order #为PK。
Order_Item(Order #, Item ID, Item Description, Item Price, Item Quantity, Total Price),其中Order #和Item ID为联合主键,Order #为FK。
如此,小k觉得,第一范式,简单的说就是没有嵌套表/嵌套记录。
3.再深入一些
还是以一开始的职工电话的例子来说:
- 如果我们选择职工号作为PK(也就是用职工号标识一行记录),那么例子中所示的情况是不符合第一范式的;
- 如果我们选择电话号码作为PK(也就是用电话号码来标识一行记录),那么例子中的情况符合第一范式,但不符合第三范式(第三范式是指不含有传递依赖,也即不存在依赖于非主属性的属性)。
而在设计关系型数据库时,第一范式是必须要满足的,是否要达到第三范式则需要根据性能等因素综合考虑。
所以,选择从不同的角度看问题,可能得到的答案或解决方案也不同。