欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  后端开发

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

程序员文章站 2022-05-09 09:26:34
...
本人菜鸟,有个问题困惑了我挺久,今天决定提出来问问大家正确或常用的做法

举个简单的例子

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

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

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

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

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

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

恳请各位不吝赐教,谢谢

回复内容:

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

举个简单的例子

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

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

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

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

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

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

恳请各位不吝赐教,谢谢

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

关系型数据库中绝大部分的表,建议有唯一的主键(包括你说的自增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、 这样的数据是不是不能修改?
在数据库设计中,无论如何也该设计一个自增ID字段作为主键吗?

主键自增主要是方便

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

能不能不这样做

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

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

总结:

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

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

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

不一定非要加主键

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

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

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

这个肯定不是了。

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

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

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

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

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


例子说明:

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

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

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

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