主键设计,想看看大家的做法?

永生天地 2010-10-20 02:35:30
最早工作时,我们的项目中主键基本都是和业务关系很紧密的,一般都是业务上用到的code,因此有很多复合主键。

后期不知道是哪个大仙来了,提出来要用无意义的自增,又或者是guid之类的,与业务无关,因此所有表就一个主键。

后来换了工作(外包的),发现他们用mysql,主键是根据业务需要编出来的code,又会出来很多复合主键。

大家都用数据库,我很想知道更多的项目是如何来考虑主键的设计的?

好久不来了,散一下分吧。
...全文
606 53 打赏 收藏 转发到动态 举报
写回复
用AI写文章
53 条回复
切换为时间正序
请发表友善的回复…
发表回复
jyh070207 2012-01-31
  • 打赏
  • 举报
回复
根据需求来,如有唯一编号或单号的,就以唯一的编号或单号做为主键,没有的话就用自增的id(identity),
一般主从表结构中, 主表的编号或单号为主键,从表以id为主键,在从表的单号上建索引
唐诗三百首 2012-01-31
  • 打赏
  • 举报
回复
2010年的帖了,楼主还是结了吧.
shengr617 2012-01-31
  • 打赏
  • 举报
回复
我觉得还是根据业务需求,怎么好就怎么设。向各位高人学习中。
SQLCenter 2010-10-21
  • 打赏
  • 举报
回复
这个问题,看看例子数据库里面是怎么做的,就一目了然了。
claro 2010-10-21
  • 打赏
  • 举报
回复
1、不可教条。
2、选合适的。
3、选简便的。
jiao3630 2010-10-21
  • 打赏
  • 举报
回复
identity, newid()只要能标识唯一 怎么方便怎么来
obuntu 2010-10-21
  • 打赏
  • 举报
回复
其实就一句话,看情况而定。

另外,不建议使用guid,第一是空间大,第二是无序性。
Passage2011 2010-10-21
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 fredrickhu 的回复:]
surrogate key,指添加的无意义的列来作为主键,一般是用identity列。
这个用得比较多 简单名了 也是唯一的

不过涉及到一个问题

identity列一旦删除了会导致缺号 这样有什么会有一定的麻烦
[/Quote]
删除用一个字段标记,不是delete
feilniu 2010-10-21
  • 打赏
  • 举报
回复
参考资源:
1. 《SQL编程风格》(ISBN:978-7-115-18582-2)一书3.13节和第五章的论述。
2. http://en.wikipedia.org/wiki/Natural_key
3. http://en.wikipedia.org/wiki/Surrogate_key
feilniu 2010-10-21
  • 打赏
  • 举报
回复
个人的一点想法:

自然键(Natural Key)和替代键(Surrogate Key)的争论是执迷于表相,偏离了数据库设计的本质。

在数据库设计中,一个表是一类事物(物件object和事实fact的统称)的集合,表的字段是用来描述各类事物的概念;表的每行记录表示一个该类事物,该记录在各个字段的值描述了该事物的特征(即特征向量),主键是一个特殊的字段——它是该事物的唯一标识。

所以,一个好的数据库设计,要保证系统中的每个表(事物)和字段(概念)都是有意义的。只有这样,才能最大限度保持业务系统在逻辑上与现实业务的对应,才能降低开发、维护、运营人员的理解成本。KISS原则

主键字段特殊之处在于:1. 主键常常需要作为其它表的外键被引用;2. 主键通常会被定义为聚集索引。这两点使得主键的字段数量和空间大小成为影响开发效率和运行性能的很重要的问题。

因此,对于自然的、在现实世界有意义的编码,如日期、邮编、社会保险号等,(通常是社会约定俗成,或由权威机构定义),往往可以采用自然键。对于在现实世界没有直接意义、需要自己定义的编码,如用户编号、订单号、产品编码、等,则需要自己用系统生成,这种情况被称为替代键。

常用的替代键的生成方式:1. 预定义,即按一定规则编制,如学校的学号可能是“学生类型+入学年份+学院专业+班级+班级内编号”、员工号可能是“E000001”这样的前辍+编码的形式。2. 纯自动生成,如GUID或自增序列,这种是比较偷懒的方式。

尽管替代键不是自然原本就有的,但经过定义和生成之后,每个替代键作为一个系统内的概念和事物的标识,就具有了业务意义。比如系统的订单号可能仅仅是自增类型的一个3000001,但经过定义之后,这就表示一个订单,这就是有意义的。

换言之,选择主键的标准,不在于它的生成方式是自然键还是替代键,而在于经过定义之后它要保证在业务系统中有意义,同时尽量满足唯一、稳定、熟悉性、可验证、简单、空间小的要求。

举例说明:

比如对于一个SNS网站系统:
用户表示一个网站的使用者,通常是内部生成UserID,一个UserID可以绑定一个或多个(看系统设计需求)Email地址或OpenID(Google/Yahoo等提供的验证服务)。这个内部UserID可能是GUID或自增整数,但一个UserID就严格地表示一个网站用户。(争论它是自然键还是替代键有意义吗?)
假如这个SNS网站是关于读书的,那么网站系统需要有书这样事物,是采用ISBN还是自定义BookID,通常后者比较好。通过自增整数生成BookID,但同时需要用唯一约束限定一个BookID只能有一个ISBN10或ISBN13。
对于用户收藏书这件事情,用户与书是多对多关系,定义用户收藏表UserFavorite(#UserID,#BookID,CollectTime),但一个用户对一本书只有收藏或未收藏两种状态,所以用(UserID,BookID)作为复合主键是自然的选择。用户收藏表通常不是被其它表引用,其主键不需要作为其它表的外键,因此如果在这个表里添加一个自增主键ID,没有任何意义,而且还需要在(UserID,BookID)上添加唯一约束。浪费一个ID的4个字节,浪费一个额外索引的空间,更重要的,多增加一个无意义ID,还浪费更宝贵的资源——开发人员的注意和精力。
jxcyz228 2010-10-21
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 billpu 的回复:]
补充一下,我9楼说的那个员工信息表的问题
因为业务情况的不可测,造成对有意义主键的失控
前一阵单位里有一个员工离职了,员工号当然作废的.过了半年之后,让我吃惊的是这个员工又回来了.这下好了,人事来找我商量说想给这个员工原来的工号,但是录入系统提示这个员工号已经存在.(因为我把员工号当作主键标识,员工临时只是加了字段tag,并没有真正删除记录).说出问题了.
然后就和人事进行了激烈的辩论,这种……
[/Quote]

不说主键的事。就说这个员工号,我一般是设计一个“是否离职”字段。因为员工号在下游很多表中都会有。所以一般不允许删除。除非是刚录入的数据。
SQL77 2010-10-21
  • 打赏
  • 举报
回复
根据需求来呗,如果主键列真的过多,用IDENTITY列还是可以的,貌似我们用的比较少
gdk123 2010-10-21
  • 打赏
  • 举报
回复
看着大家的想法,我觉着自己还没入门,哎。。。
louisit 2010-10-21
  • 打赏
  • 举报
回复
guid,identity用的比较多
Versus1008 2010-10-21
  • 打赏
  • 举报
回复
xiaoxiangqing 2010-10-21
  • 打赏
  • 举报
回复
identity作为主键比较多
fellowcheng 2010-10-21
  • 打赏
  • 举报
回复
guid,identity用的比较多
「已注销」 2010-10-21
  • 打赏
  • 举报
回复
尽量根据实际业务来设定主键
如果实际状况下不太需要主键的话,设定自增列为主键也是不错的建议,应该比没有要好些。
ws_hgo 2010-10-21
  • 打赏
  • 举报
回复
.........
Mr_Nice 2010-10-21
  • 打赏
  • 举报
回复
之前做的项目里面,PK 还是用跟业务相关的Code来定义的。
无意义代码固然有一定的特性,但是具体使用中,数据的可读性会来的更重要一些。
加载更多回复(30)

34,591

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server相关内容讨论专区
社区管理员
  • 基础类社区
  • 二月十六
  • 卖水果的net
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧