在数据库设计中,无论如何也该设计一个自增ID字段作为主键吗?

mokeyjay
  • 661

本人菜鸟,有个问题困惑了我挺久,今天决定提出来问问大家正确或常用的做法

举个简单的例子

文章表: id,标题,内容,……
标签表: id,标题

以上两张表显然都是需要自增ID作为主键以确保唯一性的

接下来要设计一个关联表,把文章和标签之间关联起来

文章标签关联表: id,文章id,标签id

可以看出实际上我只需要后面两个字段就能够实现功能了。这是否意味着我完全可以放弃自增的id字段呢?甚至是可以放弃使用主键,单纯加索引就行了呢?

如果自增ID主键不是必须的,请问我该如何判断是否需要它?仅仅通过业务需求来判断吗?

恳请各位不吝赐教,谢谢

回复
阅读 7.3k
11 个回答

首先说一下主键和索引概念上的不同,主键只是个声明,通过哪些字段能标识出表的唯一纪录,只不过是通过唯一索引实现的。

关系型数据库中绝大部分的表,建议有唯一的主键(包括你说的自增ID或UUID方式),属于逻辑主键的范围,主要是为了程序后续开发方便,尤其是在Web应用上,这个Id可以很方便的在超链接中作为参数传递,如:editPost.do?id=123

在你说的文章标签关联表的例子中,一般会在文章展示和编辑页面中,显示关联的标签,就像segmentfault在提问的页面会显示所属的标签一样,如果没有这个id,编辑时删除一个标签,假设是通过一个Ajax请求实现的,可以按照这样的url:deleteTagOfPost.do?id=123,如果没有的话就会麻烦很多,需要把能够确定这一行记录的多个字段值都放到参数中,如:deleteTagOfPost.do?postId=123&tagId=456,显然有逻辑主键会更方便一些。

另外,用多个字段的组合作为主键来确定唯一的记录行,属于物理主键的范畴,是和业务的规则强相关的,在开发的方便性、扩展性上不如逻辑主键。

首先要明确,主键是用来唯一确定一条记录行的。无论是一个字段或者多个字段的组合,嗯,一个表允许设置多主键来唯一确定一条记录。

用自增ID,比如文章,都是单一计数的,一篇文章一个ID标记即可,自增ID可以设置初始值和步进值,一般初始值和步进值默认为1,这些在建表时造成,后续程序员不用单独为这个字段再写代码,比较简洁,而且INT值比较省空间。

但是用自增ID不是唯一作为主键的方法,比如遇到大量数据时还可以用UNID来作为主键,确保没有重复主键记录。

还有如上说的多个字段作为主键,来确定唯一记录行,都可以。

用自增ID纯粹比较方便而已。

首先纠正错误

@Super盒子

没有自增主键是无法修改数据的……

你能确定吗?
果真如你所说,那请问:
1、 下面这数据有主键自增吗?
2、 这样的数据是不是不能修改?
图片描述

主键自增主要是方便

主键自增主要就是为了方便,让数据库中的int自增,保证主键唯一性。跟数据能不能修改没有任何关系,至于怎么用看个人习惯,跟实际项目需求了。

能不能不这样做

我的做法是让程序生成一个主键,方法是 时间戳+随机数,附上PHP的方法:

<?php
    $key = time().mt_rand(1000, 9999);
?>

这样子生成的主键(小项目是这么用的)看起来整齐。你用自增的方式:1、2、3、4...10000、3000000000001这样的主键看起来是不是有点怪(我有强迫症),再说了如果把ID为2的删除了。就成了这样1、3、4...10000、3000000000001;觉得是不是又不好看了,当然了只有强迫症这么觉得。

总结:

我觉得只要把握住主键唯一性,至于如何生成主键,选择方式很多,int自增、时间戳+随机数、表数据中能保证唯一的列都是可以的。这种自增的int似乎被很多人看着不爽(我的老师就觉得不合适),现在想想似乎有些怪异。
纯属个人观点,欢迎拍砖指正!

经验之谈,如果用有意义的字段做A表主键,业务中涉及更新操作,关联的表B表的外键会失效。如果设置外键约束,数据库会不允许你修改此字段值。
如果有一个无意义的id做主键,逻辑上没有任何影响,但是开发起来会方便很多

segmentfault
  • 4
新手上路,请多包涵

个人人文,id并不是必须的,但是,这是个好的习惯,所以,最好在你每个表都有一个和无意义的ID来标识这条记录。
另外,ID不一定是自增的,可以有不同的ID生成策略

不一定非要加主键

1、不一定必须加主键
2、主键不一定必须是自增ID
3、很多时候用GUID做为主键更合适

我觉得楼主应先分析业务需求,根据需求来定。业务主键好+GUID做数据库的主键比较好。

不一定要有自增主键。
在mysql中innodb建议每张表要有一个自增主键。
自增主键会作为表的聚焦索引。
没有自增主键会选择一个唯一的不为null的索引作为主键索引。
没有这样的索引,innodb会有一个隐藏的rowid作为聚焦索引,这个索引不能够引用。(oracle中可以)。
sql查询时, 索引的大小对查询速度会有略微的影响。

这个肯定不是了。

定义主键的目的是为了查询出当前表中唯一行的数据,以便于后期的更新或删除操作

常见定义主键的方式就是自增长;但并非必须要定义自增长来设置为主键;

首先得理解主键的含义了:一个表必须定义主键,且主键只能有一个

一个主键不等于一个字段这点也必须理解

一个主键可以由多个字段共同组成一个主键。但必须组合后,在当前表里需唯一


例子说明:

单一主键(单字段): 比如用户表:一般定义那就是uid作为主键。

联合主键(多字段):
如用户表、部门表、用户部门关联表
用户表:主键uid;
部门表:主键department_id
用户部门关联表:uiddepartment_id 联合主键(一个人不可能在同一部门有两个名号吧)

最直观的影响就是,如果你用有用的字段做主键那么这个字段不能为null,且该字段内容不可修改。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
你知道吗?

宣传栏