http://blog.sina.com.cn/s/blog_8020e4110101befz.html

表的主键应当不具有任何业务含义 (2012-12-17 15:10:36)转载▼

标签: it 分类: DB/SQL

表的主键应当不具有任何业务含义

表通过主键来保证每条记录的唯一性,表的主键应当不具有任何业务含义,因为任何有业务含义的列都有改变的可能性。关系数据库学的最重要的一个理论就是:不要给关键字赋予任何业务意义。假如关键字具有了业务意义,当用户决定改变业务含义,也许他们想要为关键字增加几位数字或把数字改为字母,那么就必须修改相关的关键字。一个表中的主关键字有可能被其他表作为外键。就算是一个简单的改变,譬如在客户号码上增加一位数字,也可能会造成极大的维护上的开销。

为了使表的主键不具有任何业务含义,一种解决方法是使用代理主键,例如为表定义一个不具有任何业务含义的ID字段(也可以叫其他的名字),专门作为表的主键。

——孙卫琴《精通Hibernate:Java对象持久化技术详解

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/jackie_lee/archive/2006/08/01/1007948.aspx

=======================================

昨天令狐因为处理动网论坛的数据库时,发现它是用帖子号来作为主键,由于无意中对它作了一些修改,导致帖子的关联变得混乱了。于是我们讨论了一下数据库表中主键的选择问题。因为对动网论坛的程序不熟,所以我也不知道它是怎么设计实现的,今天令狐把JavaEye上的一个关于这个方面的话题拿来讨论就好办了。

我起初也觉得用一个无意义的逻辑主键是一个好办法,至少说用一个字段就可以唯确定一条记录,使用上会很方便,速度应该也会快些。但是看了JavaEye那个帖里的讨论,以及在QQ群里的讨论后,我发现不完全是这样的。

其实这是两种不同的设计思路,谈不上用逻辑主键一定比用业务主键好。

用业务主键是传统的C/S应用开发的思路,包括我现在用的SAP里,也大量使用业务主键。但如果用O/R Mapping,则可能用逻辑主键好一些。

为对于传统C/S应用来说,以典型的两层结构看,前端处理的是一个数据表示的工作,后端处理的是一个数据持久化的工作。业务逻辑分散在两端,特别是在后

端。因为需要在后端通过Stored

Procedure和View等来实现业务逻辑,应用直接与关系数据库打交道,所以数据的记录不但要求便于程序访问,对开发者来说,还要易读。也就是说需

要数据库的关系逻辑能够清晰地表达出业务逻辑来。主键采用业务主键是自然甚至是必须的。

而ORM应用恰恰相反。它需要一个最简单的

办法来标记一条唯一记录,但不需要有具体的意义,就像在OOP中,我们访问一个Object总是通过指针(或相似的引用),但我们并不需要知道这个指针具

体的值是0x89ABCDEF还是0xFEDCBA98。逻辑主键就相当于一个指针,当别的关联表引用到这条记录时,用一个外键字段记录了这个逻辑主键,

就相当于那个Object中有一个属性记录了一个指向这个Object的指针。这时如果用业务主键-特别是复合业务主键-就是存心给自己打麻烦了。最

糟糕的情况就是当需要修改这个业务主键的值的时候,会导致所有的关联发生混乱-在传统C/S应用中,我们是用Trigger来解决这个问题,但是在

ORM中不可能这样做,否则那还要ORM干什么?

当然,对于开发者来说,在ORM这样的情况下,用逻辑主键存在一个至关重要的问题

就在于数据的可读性将要变差。也就是说,除非通过OO的视角来看数据才是易于理解的。但如果直接进入后端看关系数据库,将变得困难。因此,基本上,逻辑主

键与ORM是相辅相成的,缺一不可,并且采用ORM的开发者要尽可能避免与后端的关系数据打交道,否则就会非常的痛苦。

正如令狐所作的总结:一个是从OO角度看,一个是直接深入数据库内部看。

关于数据库表应该采用逻辑主键还是业务主键的讨论

=============================

数据库主键不应该具有任何业务意义

关系数据库学的最重要的一个理论是:不要给关键字赋予任何业余意义。假如关键字具有了业务意义,当用户决定业务含义,也许他们想要为关键字增加几位数字或者把数字改为字母,那么就必须修改相关的关键字。一个表中的主关键字有可能被其他表做为外键。就算是一个简单的改变,也可能会造成极大的维护上的开销。

为了使表的主键不具有任何业务意义,一种解决办法是使用代理主键,例如为表定义一个不具有任何业务含义的ID字段(也可以叫其他名字),专门做为表的主键。

我回顾我以前设计的很多数据库,都在某些地方没有考虑周到,即使大部分的主键都没有业务意义,还是会有某些表的主键和业务联系起来。因为我一直认为,主键是用来保持唯一性的,之所以要有代理主键,是因为有一些记录的内容没办法保持唯一性。例如设计一个用户表,用户的名字有可能重复,这个人可能叫blue,那么人也可能叫blue。这样就需要一个ID来分清。

由于我之前的想法,导致我数据库设计上的一些错误。例如我曾经在一次数据库设计中使用一个ID来做为一个表的主键,该表是记录一些报表的。每个报表上都有一个ID,这个ID是具有业务意义的,是可以让客户输入,也可以自动生成的,但是客户说明这个ID是唯一的,是数字类型。因此由于它的唯一性,我在数据库中设计这个ID为数字类型的。但是到了后来客户要求使用文字类型的,例如原来的是"111111”,他要求可以写成"11111A”,“11111B”。这个时候由于这个ID做了很多表的外键,就会产生很多维护上面的麻烦。即使在数据库表之间做了级联更新和级联删除,修改数据类型还是很麻烦的事情。

这次RFID项目数据库设计我原来想使用RFID标签的ID做为产品的主键,因为RFID标签ID具有唯一性,使用它作为主键在查找的时候速度应该会快些。但是后来发现问题并不是这么简单。如果使用RFID标签ID做为主键,那么就具有了业务意义。当产品表和其他表关联,产品表的主键做为其他表的外键的时候,如果出现一些业务上的情况,例如RFID标签坏了,要更换,就会产生更改主键内容的问题了。

回顾一下,还是发现自己的基础不扎实。学习数据库的时候都不去上课。少年不努力,老大徒悲伤。

====================================

数据库中主键和外键的设计原则

主键和外键是把多个表组织为一个有效的关系数据库的粘合剂。主键和外键的设计对物理数据库的性能和可用性都有着决定性的影响。

必须将数据库模式从理论上的逻辑设计转换为实际的物理设计。而主键和外键的结构是这个设计过程的症结所在。一旦将所设计的数据库用于了生产环境,就很难对这些键进行修改,所以在开发阶段就设计好主键和外键就是非常必要和值得的。

主键:

关系数据库依赖于主键-它是数据库物理模式的基石。主键在物理层面上只有两个用途:

  1. 惟一地标识一行。

  2. 作为一个可以被外键有效引用的对象。

基于以上这两个用途,下面给出了我在设计物理层面的主键时所遵循的一些原则:

  1. 主键应当是对用户没有意义的。如果用户看到了一个表示多对多关系的连接表中的数据,并抱怨它没有什么用处,那就证明它的主键设计地很好。

  2. 主键应该是单列的,以便提高连接和筛选操作的效率。

注:使用复合键的人通常有两个理由为自己开脱,而这两个理由都是错误的。其一是主键应当具有实际意义,然而,让主键具有意义只不过是给人为地破坏数据库提供了方便。其二是利用这种方法可以在描述多对多关系的连接表中使用两个外部键来作为主键,我也反对这种做法,理由是:复合主键常常导致不良的外键,即当连接表成为另一个从表的主表,而依据上面的第二种方法成为这个表主键的一部分,然,这个表又有可能再成为其它从表的主表,其主键又有可能成了其它从表主键的一部分,如此传递下去,越靠后的从表,其主键将会包含越多的列了。

  1. 永远也不要更新主键。实际上,因为主键除了惟一地标识一行之外,再没有其他的用途了,所以也就没有理由去对它更新。如果主键需要更新,则说明主键应对用户无意义的原则被违反了。

注:这项原则对于那些经常需要在数据转换或多数据库合并时进行数据整理的数据并不适用。

  1. 主键不应包含动态变化的数据,如时间戳、创建时间列、修改时间列等。

  2. 主键应当有计算机自动生成。如果由人来对主键的创建进行干预,就会使它带有除了惟一标识一行以外的意义。一旦越过这个界限,就可能产生认为

=====================

http://www.cnblogs.com/tianyamoon/archive/2008/04/02/1134394.html

以下是我的想法:

全部不根业务挂钩,还要联合主键干什么,可读性也会降低,我现在的一般的做法是:全部都跟业务有关,如果确实需要再增加一个系统主键,给系统使用,业务人员从不关心系统主键,如果按照以上理论,那系统主键也只能采用identify,而不能采用autoId,然后关联,合并的才会好用,并且每一个表都要这个主键。

我一般都不会使用autoId, CreateTime, LastedUpdateTime,采用最小化原则设计,全部与业务相关,如果确实需要再增加这些通用的数据字段~~~,

主要看需求,看当前的需求,五年之后的事情五年之后再想,谁又能预测未来呢~~`

oo是oo,关系型数据