`
java-mans
  • 浏览: 11421914 次
文章分类
社区版块
存档分类
最新评论

主键的选择

 
阅读更多

Recently we are going on the School System(教务系统)。Our group is in charge of the Basic Information part.设计和操作数据库,is almost our whole work.

设计数据库阶段,首先,分析需要建哪些表,每张表设计哪些字段;再设计主键和外键,修改和完善数据库。

When I came to the Primary Key, something puzzled me:有些主键,比如xx记录表,主键是int自增类型;而有些,我们选择用编号来作为主键(比如楼号,学号)。然后问题来了,用编号作为主键,当该条信息修改时,以前的记录就被冲掉了,可是我想在数据库保留存在过的所有记录。Well,may be I go wrong.

但是,忽略这两种选择方式,他们都是主键。那么什么是主键,它存在的意义在哪里,它又是做什么的呢?

主键,“主关键字(primary key)是表中的一个或多个字段,它的值用于惟一地标识表中的某一条记录”。

作用:(1)唯一区分每条记录的字段;(2)本记录的修改与删除;(3)用于其它表的外键关联。当我们没有主键时,这些操作会变的非常麻烦。

在我的意识中,每张表都应该有它的主键,主键的存在代表着表结构的完整性。

那么,怎样选择主键??读到一篇文章,提到主键的选择:

(1)编号

采用实际业务中的唯一字段的“编号”作为主键设计,这在小型的项目中是推荐这样做的,因为这可以使项目比较简单化,但在使用中却可能带来一些麻烦。比如上面提到的修改数据时,只能保存现有数据,而不能保存历史数据。还有,要进行“编号修改”时,可能要涉及到很多相关联的其他表,“后果很严重”,当然我们尽量避免。(2)自动增长

就是新建一个ID字段,自动增长。自动增长型字段允许我们在向数据库添加数据时,不考虑主键的取值,记录插入后,数据库系统会自动为其分配一个值,确保绝对不会出现重复。使用SQL Server数据库,我们还可以在记录插入后使用@@IDENTITY全局变量获取系统分配的主键键值。

优点:数据库自动编号,速度快,而且是增量增长,聚集型主键按顺序存放,对于检索非常有利;数字型的,占用空间小,易排序,在程序中传递也方便;如果通过非系统增加记录(比如手动录入,或是用其他工具直接在表里插入新记录,或老系统数据导入)时,非常方便,不用担心主键重复问题。

缺点:其实缺点也就是来自其优点,就是因为自动增长,在手动要插入指定ID的记录时会显得麻烦,尤其是当系统与其他系统集成时,需要数据导入时,很难保证原系统的ID不发生主键冲突(前提是老系统也是数字型的);如果其他系统主键不是数字型那就麻烦更大了,会导致修改主键数据类型了,这也会导致其他相关表的修改,后果同样很严重;就算其他系统也是数字型的,在导入时,为了区分新老数据,可能想在老数据主键前统一加一个“o”(old)来表示这是老数据,那么自动增长的数字型又面临一个挑战。

(3)Max加一

由于自动编号存在那些问题,所以有些朋友就采用自己生成,同样是数字型的,只是把自动增长去掉了,采用在Insert时,读取Max值后加一,这种方法可以避免自动编号的问题,但也存在一个效率问题,如果记录非常大的话,那么Max()也会影响效率的;更严重的是并发性问题,如果同时有两人读到相同的Max后,加一后插入的ID值会重复。

(4)自制加一

考虑Max加一的效率后,有人采用自制加一,也就是建一个特别的表,字段为:表名,当前序列值。这样在往表中插入值时,先从此表中找到相应表的最大值后加一,进行插入。有人可能发现,也可能会存在并发处理,这个并发处理,我们可以采用lock线程的方式来避免,在生成此值的时,先Lock,取到值以后,再unLock出来,这样不会有两人同时生成了。这比Max加一的速度要快多了。

但同样存在一个问题:在与其他系统集成时,脱离了系统中的生成方法后,很麻烦保证自制表中的最大值与导入后的保持一致,而且数字型都存在上面讲到的“o”老数据的导入问题。因此在“自制加一”中可以把主键设为字符型的。字符型的自制加一我倒是蛮推荐的,应该字符型主键可以应付很多我们意想不到的情况。

(5)GUID主键

GUID是可以自动生成,也可以程序生成,而且键值不可能重复,可以解决系统集成问题,几个系统的GUID值导到一起时,也不会发生重复,就算有“o”老数据也可以区分,而且效率很高,在.NET里可以直接使用System.Guid.NewGuid()进行生成,在SQL里也可以使用 NewID()生成。

优点是:

同 IDENTITY 列相比,uniqueidentifier 列可以通过 NewID() 函数提前得知新增加的行 ID,为应用程序的后续处理提供了很大方便。

便于数据库移植,其它数据库中并不一定具有 IDENTITY 列,而 Guid 列可以作为字符型列转换到其它数据库中,同时将应用程序中产生的 GUID 值存入数据库,它不会对原有数据带来影响。

便于数据库初始化,如果应用程序要加载一些初始数据, IDENTITY 列的处理方式就比较麻烦,而 uniqueidentifier 列则无需任何处理,直接用 T-SQL 加载即可。

便于对某些对象或常量进行永久标识,如类的 ClassID,对象的实例标识,UDDI 中的联系人、服务接口、tModel标识定义等。

缺点是:

GUID 值较长,不容易记忆和输入,而且这个值是随机、无顺序的

GUID 的值有 16 个字节,与其它那些诸如 4 字节的整数相比要相对大一些。这意味着如果在数据库中使用 uniqueidentifier 键,可能会带来两方面的消极影响:存储空间增大;索引时间较慢。

分享到:
评论

相关推荐

    聚簇索引与主键的选择

    MyISAM引擎中三、聚簇索引的优劣与主键选择的关系 一、什么是聚簇索引? 首先,聚簇索引不是一种单独的索引类型,其实是数据的存储方式。聚簇索引将数据存储与索引放在了一起,找到了索引也就找到了数据。 在MySql...

    sqlserver无主键表的同步方案1

    背景介绍对sqlserver做数据库同步的时候,由于医院服务器和数据库版本的限制,选择了用发布订阅处理数据库同步,但是这个方式只能处理有主键的表,对于无主键的表

    主键的选择1

    但是,一旦我们在此时重启
MySQL
的话,这张表的主键将会发生回溯,也就是
user
表的自增起始值将重新变为
3在
MySQL
8.0
之前主键回溯问题并没

    I2U正式库数据修改辅助工具V1.3

    这是一个将Insert语句转化为Update语句,同时支持主键选择与数据库名称输入的工具软件。对于线上库(或称正式库)上数据(特别是数据量较大时)的修改,以及线上库与测试库字段数量不一致情况下的修改,能够起到...

    I2U线上库正式库数据修改辅助工具

    这是一个将Insert语句转化为Update语句,同时支持主键选择与数据库名称输入的工具软件。对于线上库(或称正式库)上数据(特别是数据量较大时)的修改,以及线上库与测试库字段数量不一致情况下的修改,能够起到...

    I2U正式库数据修改辅助工具V1.4

    这是一个将Insert语句转化为Update语句,同时支持主键选择与数据库名称输入的工具软件。对于线上库(或称正式库)上数据(特别是数据量较大时)的修改,以及线上库与测试库字段数量不一致情况下的修改,能够起到...

    总结hibernate常用主键生成策略。

    1主键常用的生成策略 2对数据库的依赖性总结 3关于主键生成策略的选择 详细解释

    Mysql主键和唯一键的区别点总结

    表中的主键值很少更改,因此在选择主键是需要小心,要选择很少发生更改的地方。一个表的主键可以被另一个表的外键引用。 为了更好地理解主键,我们创建一个名为Student的表,它具有roll_number、name、batch、phone_...

    小议数据库主键选取策略

    我们在建立数据库的时候,需要为每张表指定一个主键,所谓主键是能够标识表中某一行的属性或属性组,一个表只能有一个主键,但可以有多个候选索引。因为主键可以标识某一行记录,所以可以确保执行数据更新、删除的...

    MySQL索引之主键索引

    在MySQL里,主键索引和辅助索引分别是什么意思,有什么区别? 上次的分享我们介绍了聚集索引和非聚集索引的区别,本次我们继续介绍...3、不选择会动态更新的类型,比如当前时间戳等。 这么做的好处有几点: 1、新增数据

    带有lombok的可以自定义插件、方法的mybatis自动化代码生成器

    selectByPrimaryKey 按主键选择 updateByPrimaryKeySelective 按主键更新所选字段 updateByPrimaryKey 按主键更新 selectOne 查询一个 selectList 查询列表 selectAll 查询所有记录 insertBatch 批插入 ...

    为什么说InnoDB必须要有主键并且推荐使用自增整型主键呢?

    1.InnoDB存储引擎的数据结构必须需要一个主键才可以组织起来,如果用户使用InnoDB存储引擎建立表的时候,没有指定主键,则Mysql会自动的帮你找到一个合适的唯一索引...Mysql中innodb_page_size = 16kb,选择BIGINT作为主

    sqlserver主键设计的注意点

    常常有人称呼主键为内部标识,为什么会这样称呼,原因之一在于“内部”,所谓内部从某种程度上来说就是指表记录,从大的范围来说就是数据库,如果你在设计的时候选择了对用户来说有意义的信息来作为主键,那么迟早会...

    design-in-c-final-project

    设计手册由于该项目的时间紧迫,它使用命令行界面与用户进行交互。命令行界面: 要构建项目,请运行以下命令:make 这将创建一个名为main的可执行文件。... SELECT-使用主键选择数据DELETE-使用主键从表中删除值提示中

    Navicat Premium中Oracle创建主键自增的方法

    1.选中表进入设计,选择触发器, 触发器名称,混合不选,每行,触发前,插入时,启用 2.下面展示触发器代码。 // An highlighted block BEGIN SELECT SEQ_EXAM_KNOWLEDGE_BASE.nextval INTO :NEW.ID FROM DUAL;...

    HeidiSQL(Mysql 管理 图形)

    此外,你可以从文本文件导入数据,运行 SQL查询,在两个数据库之间同步表以及导出选择的表到其它数据库或者 SQL 脚本当中。HeidiSQL 提供了一个用于在数据库浏览之间切换 SQL 查询和标签带有语法突出显示的简单易用...

    Backend-Project-210114:使用主键和外键的“多对多”数据库关系

    使用主键和外键的“多对多”数据库关系。 该项目的目标是为一个通用的国际非政府组织创建一个完整的全栈项目的初始后端。 我们选择了亚洲,并将该非政府组织指定为亚洲非政府组织(ANGO)。 前端分为两个部分,即...

    MySQL中主键索引与聚焦索引之概念的学习教程

    不选择会动态更新的类型,比如当前时间戳等。 这么做的好处有几点: 新增数据时,由于主键值是顺序增长的,innodb page发生分裂的概率降低了;可以参考以往的分享“[MySQL FAQ]系列 — 为什么InnoDB表要建议用自增列...

    获取DataList控件的主键和索引实用图解

    解决你的问题,可以尝试获取选择行的索引或是主键即可,能获取到主键,其它字段的值,也可以获取到了。 下图中,高亮选择区,即是针对问题解决而在原在代码添加的部分。一是在DataList控件添加一个DataKeyField,...

Global site tag (gtag.js) - Google Analytics