名站网址导航为大家提供关于数据库教程相关的教程网站知识。
因为主键可以唯一标识某一行记录,所以可以确保执行数据更新、删除的时候不会出现张冠李戴的错误。当然,其它字段可以辅助咱们在执行这些操作办法时消除共享冲突,不过就不在这里讨论了。主键除了上述作用外,常常与外键构成参照完整性约束,防止出现数据不一致。所以网站数据库在设计时,主键起到了很重要的作用。SQL数据库语句 一个简单的字符串分割函数
复制具体相关代码 具体相关代码如下:,CREATE FUNCTION dbo.f_splitstr( @str varchar(8000) )RETURNS @r TABLE(id int IDENTITY(1, 1), value va
常见的网站数据库主键选取相关方式有:
自动增长字段
手动增长字段
UniqueIdentifier
“COMB(Combine)”类型
一、自动增长型字段
很多网站数据库设计者喜欢使用自动增长型字段,因为它使用简单。自动增长型字段允许咱们在向网站数据库添加数据时,不考虑主键的取值,记录插入后,网站数据库系统会自动为其分配一个值,确保绝对不会出现重复。假如如果使用SQL Server网站数据库的话,咱们还可以在记录插入后使用@@IDENTITY全局变量获取系统分配的主键键值。
尽管自动增长型字段会省掉咱们很多繁琐的工作,但使用它也存在潜在的问题,那就是在数据缓冲模式下,很难预先填写主键与外键的值。假设有两张表:
Order(OrderID, OrderDate)
OrderDetial(OrderID, LineNum, ProductID, Price)
Order表中的OrderID是自动增长型的字段。现在需要咱们录入一张订单,包括在Order表中插入一条记录以及在OrderDetail表中插入若干条记录。因为Order表中的OrderID是自动增长型的字段,那么咱们在记录正式插入到网站数据库之前无法事先得知它的取值,只有在更新后才能知道网站数据库为它分配的是什么值。这会造成以下矛盾发生:
首先,为了能在OrderDetail的OrderID字段中添入正确的值,必须先更新Order表以获取到系统为其分配的OrderID值,然后再用这个OrderID填充OrderDetail表。最后更新OderDetail表。但是,为了确保数据的一致性,Order与 OrderDetail在更新时必须在事务保护下同时进行,即确保两表同时更行成功。显然它们是相互矛盾的。(此处表述有错误。吕震宇 2005-6-15)
【补充2005-6-15】---------------------------------------------
听棠.NET指出:主档放在事务中提交时,通过@@IDENTITY 就可以取到生成值的,因此可以传给明细当外键用,而且在事务发生错误回滚时,主档记录也会被回滚取消的。
吕震宇补充:使用自动增长字段会增加网络的roundTrip。尽管可以使用@@IDENTITY取得主键的值,但在更新过程中,不得不增加一次数据往返(以C/S结构为例):
1、客户端发送开始事务开始执行命令
2、客户端提交主表更新
3、 站点服务器返回@@IDENTITY
4、客户端根据返回的主键更新从表缓冲
5、客户端将从表提交站点服务器更新
6、客户端提交事务
在这里多了一次往返就会增加了事务处理的时间。降低并发性能。
假如如果不用自动增长型字段,将是以下情景:
1、客户端发送开始事务开始执行命令
2、客户端提交主表更新
3、客户端提交从表更新
4、客户端提交事务
因此我不赞成使用自动增长型字段作为主键与外键链接的纽带。
------------------------------------------------
除此之外,当咱们需要在多个网站数据库间进行数据的复制时(SQL Server的数据分发、订阅机制允许咱们进行库间的数据复制操作办法),自动增长型字段可能造成数据合并时的主键冲突。设想一个网站数据库中的Order表向另一个库中的Order表复制网站数据库时,OrderID到底该不该自动增长呢?
ADO.NET允许咱们在DataSet中将某一个字段设置为自动增长型字段,但千万记住,这个自动增长字段仅仅是个占位符而已,当网站数据库进行更新时,网站数据库生成的值会自动取代ADO.NET分配的值。所以为了防止用户产生误解,建议大家将ADO.NET中的自动增长初始值以及增量都设置成-1。此外,在ADO.NET中,咱们可以为两张表建立DataRelation,这样存在级联关系的两张表更新时,一张表更新后另外一张表对应键的值也会自动发生变化,这会大大减少了咱们对存在级联关系的两表间更新时自动增长型字段带来的麻烦。
二、手动增长型字段
既然自动增长型字段会带来如此的麻烦,咱们不妨考虑使用手动增长型的字段,也就是说主键的值需要自己维护,通常情况下需要建立一张单独的表存储当前主键键值。还用上面的例子来说,这次咱们新建一张表叫IntKey,包含两个字段,KeyName以及KeyValue。就像一个hashTable,给一个KeyName,就可以知道目前的KeyValue是什么,然后手工实现键值数据递增。在SQL Server中可以编写这样一个存储过程,让取键值的过程自动进行。具体相关代码如下:
复制具体相关代码 具体相关代码如下:
CREATE PROCEDURE [GetKey]
@KeyName char(10),
@KeyValue int OUTPUT
AS
UPDATE IntKey SET @KeyValue = KeyValue = KeyValue 1 WhERE KeyName = @KeyName
GO
这样,通过调用存储过程,咱们可以获得最新键值,确保不会出现重复。若将OrderID字段设置为手动增长型字段,咱们的程序可以由以下几步来实现:首先调用存储过程,获得一个OrderID,然后使用这个OrderID填充Order表与OrderDetail表,最后在事务保护下对两表进行更新。
使用手动增长型字段作为主键在进行网站数据库间数据复制时,可以确保数据合并过程中不会出现键值冲突,只要咱们为不同的网站数据库分配不同的主键取值段就行了。但是,使用手动增长型字段会增加网络的RoundTrip,咱们必须通过增加一次网站数据库访问来获取当前主键键值,这会增加网络和网站数据库的负载,当处于一个低速或断开的网络环境中时,这种做法会有很大的弊端。同时,手工维护主键还要考虑并发冲突等种种因素,这更会增加系统的复杂程度。
三、使用UniqueIdentifier
SQL Server为咱们提供了UniqueIdentifier数据类型,并提供了一个生成函数NEWID( ),使用NEWID( )可以生成一个唯一的UniqueIdentifier。UniqueIdentifier在网站数据库中占用16个字节,出现重复的概率非常小,以至于可以认为是0。咱们经常从注册表中看到类似
{45F0EB02-0727-4F2E-AAB5-E8AEDEE0CEC5}
的东西实际上就是一个UniqueIdentifier,Windows用它来做COM组件以及接口的标识,防止出现重复。在.NET里管 UniqueIdentifier称之为GUID(Global Unique Identifier)。在C#中可以使用如下开始执行命令生成一个GUID:
Guid u = System.Guid.NewGuid();
对于上面提到的Order与OrderDetail的程序,假如如果选用UniqueIdentifier作为主键的话,咱们完全可以避免上面提到的增加网络RoundTrip的问题。通过程序直接生成GUID填充主键,不用考虑是否会出现重复。
UniqueIdentifier字段也存在严重的缺陷:首先,它的长度是16字节,是整数的4倍长,会占用大量存储空间。更为严重的是,UniqueIdentifier的生成毫无规律可言,要想在上面建立索引(绝大多数网站数据库在主键上都有索引)是一个非常耗时的操作办法。有人做过实验,插入同样的数据量,使用UniqueIdentifier型数据做主键要比使用Integer型数据慢,所以,出于效率考虑,尽可能避免使用 UniqueIdentifier型网站数据库作为主键键值。
四、使用“COMB(Combine)”类型
既然上面三种主键类型选取策略都存在各自的缺点,那么到底有没有好的办法加以解决呢?答案是肯定的。通过使用COMB类型(网站数据库中没有COMB类型,它是Jimmy Nilsson在他的“The Cost of GUIDs as Primary Keys”一文中设计出来的),可以在三者之间找到一个很好的平衡点。
COMB数据类型的基本设计思路是这样的:既然UniqueIdentifier数据因毫无规律可言造成索引效率低下,影响了系统的性能,那么咱们能不能通过组合的相关方式,保留UniqueIdentifier的前10个字节,用后6个字节表示GUID生成的时间(DateTime),这样咱们将时间信息与UniqueIdentifier组合起来,在保留UniqueIdentifier的唯一性的同时增加了有序性,以此来提高索引效率。也许有人会担心UniqueIdentifier减少到10字节会造成数据出现重复,其实不用担心,后6字节的时间精度可以达到1/300秒,两个COMB类型数据完全相同的可能性是在这1/300秒内生成的两个GUID前10个字节完全相同,这几乎是不可能的!在SQL Server中用SQL开始执行命令将这一思路实现出来便是:
复制具体相关代码 具体相关代码如下:
关于数据库教程相关的教程网站知识今天我们就说到这里了,希望可以帮到大家。