关系型数据库主键总结

  

在基于关系型数据库设计时候,通常要为每张表指定一个主键,所谓主键就是能够唯一标识表中某一行记录的属性或属性组,一个表只能有一个主键,但可以有多个候选索引。因为主键可以唯一标识某一行记录,所以可以确保执行数据更新,删除,修改时不出现错误。当然,其它字段可以辅助我们在执行这些操作时消除共享冲突,不是本文讨论的重点,不再赘述。主键除了上述作用外,常常与外键构成参照完整性约束,防止出现数据不一致。所以数据库在设计时,主键起到了很重要的作用,常见的数据库主键选取方式有:自动增长式,手动增长式,UniqueIdentifier,联合式(复合式),时间序列+随机数式,“梳(组合)”类型。
一、自动增长式
很多数据库设计者喜欢使用自动增长型字段,因为它使用简单。自动增长式允许我们在向数据库添加数据时,不考虑主键的取值,记录插入后,数据库系统会自动为其分配一个值,确保绝对不会出现重复。如果使用SQL Server数据库的话,我们还可以在记录插入后使用@@IDENTITY全局变量获取系统分配的主键值。
尽管自动增长式字段会省掉我们很多繁琐的工作,但使用它也存在潜在的问题,那就是在数据缓冲模式下,很难预先填写主键与外键的值。假设有主辅两张表:
订单(OrderDate OrderID)订单表
OrderDetial (OrderID、LineNum ProductID,价格)订单明细表
订单表中的OrderID是自动增长型的字段。假设现在需要我们录入一张订单,包括在顺序表中插入一条记录以及在OrderDetail表中插入若干条记录。因为顺序表中的OrderID是自动增长型的字段,那么我们在记录正式插入到数据库之前无法事先得知它的取的值,只有在更新后才能知道数据库为它分配的是什么值。这会造成以下矛盾发生:
首先,为了能在OrderDetail的OrderID字段中添入正确的值,必须先更新订单表以获取到系统为其分配的OrderID值,然后再用这个OrderID填充OrderDetail表的OrderID列。最后更新OderDetail表。但是,为了确保数据的一致性,秩序与OrderDetail在更新时必须在事务模式下进行的,即要么两张表同时同时更新成功,要么全部失败,显然它们是相互矛盾的。
其次,当我们需要在多个数据库间进行数据的复制时(SQL Server的数据分发,订阅机制允许我们进行库间的数据复制操作),自动增长式字段可能造成数据合并时的主键冲突及表关联关系的丢失。设想一个数据库中的顺序表向另一个库中的顺序表复制数据库时,OrderID到底该不该自动增长呢?如果自动增长,其子表OrderDetial的关联关系会丢失,如果不增长就会和现有数据主键重复,是不是很矛盾呢?
再次,自增量的值都是需要在系统中维护一个全局的数据值,每次插入数据时即对此次值进行增量取值。当在产生唯一标识的并发环境中,每次的增量取值都必须为此全局值加锁解锁以保证增量的唯一性。造成并发瓶颈,降低查询性能。
还有当数据表足够大或频繁的更改和插入操作导致主键类型值超出范围,这种情况一般很少碰的到,但也是我们进行数据表设计时必须考虑的一个问题

  

在实际开发中中容易出现主键冲突主键冲突就是主键出现重复值
比如t_user t_admin都有主键都是id自增方式
插入t_user (id)
从t_admin选择id
两表中都有主键为7的时候插入数据不成功因为主键冲突
解决办法
更新t_admin组id=id
id不是零和id> 0

  

提交;   

二,手动增长型字段
既然自动增长型字段会带来如此的麻烦,我们不妨考虑使用手动增长型的字段,也就是说主键的值需要自己维护,通常情况下需要建立一张单独的表存储当前主键键值。为了叙述上的方便仍然利用上面的例子进行阐述,新建一张表叫IntKey,包含两个字段,KeyName以及KeyValue。就像一个散列表,给一个KeyName,就可以知道目前的KeyValue是什么,然后手工实现键值数据递增。在SQL Server中可以编写这样一个存储过程,让取键值的过程自动进行。代码如下:
创建过程[GetKey]
@KeyName char (10),
@KeyValue int输出

更新IntKey组@KeyValue=https://www.yisu.com/zixun/KeyValue=KeyValue + 1 KeyName=@KeyName

这样,通过调用存储过程,我们可以获得最新键值,确保不会出现重复。若将OrderID字段设置为手动增长式字段,我们的程序可以由以下几步来实现:首先调用存储过程,获得一个OrderID,然后使用这个OrderID填充顺序表与OrderDetail表,最后在事务机制下对两表进行更新。
使用手动增长式字段作为主键在进行数据库间数据复制时,可以确保数据合并过程中不会出现键值冲突,只要为不同的数据表分配不同的主键取值段就行了。但是,使用手动增长型字段会增加网络的负担,必须通过增加一次数据库访问来获取当前主键键值,这会增加网络和数据库的负载,当处于一个低速或断开的网络环境中时,这种做法会有很大的弊端。同时,手工维护主键还要考虑并发冲突等种种因素,这更会增加系统的复杂程度。

关系型数据库主键总结