现在的位置: 首页 > 综合 > 正文

关于获取SQL Server2000的自增长字段值

2013年10月12日 ⁄ 综合 ⁄ 共 1706字 ⁄ 字号 评论关闭

我喜欢问这些求职者一个问题:
“假设我们使用SQL Server2000进行开发。现在我需要传递给存储过程两个变量:firstname和lastname。存储过程负责向名字为TEST的表插入这两个变量,其中TEST表有两个字段,名字就叫firstname和lastname。TEST表的主键是一个自增长类型的字段,名字叫ContactID。问题是我如何获取插入的那条数据的主键值。”
错误回答 #1 - Select max(contactid) from Test.
因为你无法避免别人也同时在插入数据,因此这个回答是错误的。当然,你可以通过提升隔离级别来达到目的,但是这将会大幅降低并发性能,因此不好。
错误回答 #2 - Select top 1 contactid from test order by contactid desc.
错误的原因和回答#1一样。
错误回答 #3 - 通过插入的数据来组合成一个唯一的标识,从而获得自增长字段的值。如果插入的数据确实组合起来是唯一的,能达到目的,但是如果不唯一,怎么办呢?因此这也不是好办法。
错误回答 #4 - 这个回答很接近正解了。这些回答者建议使用@@Identity,自然这是可以的 (小心,要知道如何正确使用@@Identity), 你应该尽快获取@@Identity的值,因为其它人的对表插入数据,也会改变这个值。
- 是的,获取最后一个identity值,在大多数情况下是可行的,但是如果在TEST表上有触发器,这个触发器会自动向别的表插入数据,如果那个表也同样有一个自增长字段,那么错误就会发生。此时,你获取的@@Identity取值是那个表的identity取值(注意:这个回答正确地描述了@@Identity的行为)。
正确答案 - 因为我们使用的是SQL Server 2000,因此使用Scope_Identity() , 如果用的是SQL Server 7,那么只有只用@@Identity,并且以output参数方式传递(return值一般是用来作为错误代码用)。使用@@Identity意味着将来也许会发生错误,例如审核时使用自增长字段。
现在我们来做一系列的试验来验证:
create database IdentityTest
use identitytest
create table TEST (ContactID int not null identity (1, 1), firstname varchar(100) null, lastname varchar(100) null)
insert into TEST Default Values
select @@Identity   //运行后会返回1

insert into TEST Default Values
select Scope_Identity()//运行后会返回2
现在我们来设计如何使@@Identity返回错误结果。我们先创建一个包含一个新的自增长字段的表TESTHISTORY,然后在TEST表上加触发器。
create table TESTHISTORY (HistoryID int not null identity (1, 1), ContactID int not null, firstname varchar(100) null, lastname varchar(100) null)
create trigger i_TEST on dbo.TEST for insert as
set nocount on
insert into TESTHISTORY (ContactID, FirstName, LastName) select ContactID, FirstName, LastName from Inserted

insert into TEST Default Values
select @@Identity //运行后会返回1 而不是 3 因为此时@@Identity获取的是最后一次插入的identity值,最后一次插入发生在TESTHISTORY中
insert into TEST Default Values
select Scope_Identity()//运行后会返回4 而不是2 因为此时Scope_Identity()的获取机制是当前表插入的最后一次的 identity值

抱歉!评论已关闭.