Article ID: 163446
Article Last Modified on 2/22/2005
To get the last identity value, use the @@IDENTITY global variable. This variable is accurate after an insert into a table with an identity column; however, this value is reset after an insert into a table without an identity column occurs.
Here you use a separate table to maintain the highest sequence number. This approach ensures that sequence numbers are assigned in sequential order, without any holds, by effectively single-threading inserts.
/* for 6.5 or earlier versions, add columns until each row is at least half of a 2K page so each row is on a separate page */
create table IdentityTable
(ForTable sysname not null,
Value int not null)
go
create proc GetNextIdentity @ForTable sysname, @Value int OUTPUT
AS
set nocount on
begin tran
/* if this is the first value generated for this table, start with zero */
if not exists (select * from IdentityTable where ForTable = @ForTable)
insert IdentityTable (ForTable, Value) values (@ForTable, 0)
/* update must be before select to issue a lock and prevent duplicates */
update IdentityTable
set Value = Value + 1
where ForTable = @ForTable
select @Value = Value from IdentityTable
where ForTable = @ForTable
commit tran
return @value
go
-- Example execution for the Pubs Database
declare @MyIdentity int
exec @MyIdentity = GetNextIdentity @ForTable = 'authors', @Value = 0
select @MyIdentity
Be careful, because this method may cause concurrency contention issues.
The guide also describes several other methods. However one of these
methods, using @@DBTS, should not be used because the behavior of that
feature may change in future versions.
select @@VERSION
go
use pubs
go
set nocount on
go
print ''
print 'Create the sample tables...'
print ''
go
drop table tblAudit
go
create table tblAudit
(
iID int identity(2500,1),
strData varchar(10)
)
go
drop table tblIdentity
go
create table tblIdentity
(
iID int identity(1,1),
strData varchar(10)
)
go
print ''
print 'Create the sample procedures and triggers...'
print ''
go
create table #tblIdentity
(
iID int,
strTable varchar(30)
)
go
create trigger trgIdentity on tblIdentity for INSERT
as
insert into #tblIdentity values (@@IDENTITY, 'tblIdentity')
insert into tblAudit values ('Audit entry')
go
create trigger trgAudit on tblAudit for INSERT
as
insert into #tblIdentity values (@@IDENTITY, 'tblAudit')
go
drop procedure sp_Insert
go
create procedure sp_Insert
as
insert into tblIdentity values('Test')
print ' '
print 'Simple reliance on the @@IDENTITY after the execution would
incorrectly yield'
print 'FK references of tblIdentity would be incorrect'
print ' '
select '@@IDENTITY' = @@IDENTITY
go
drop procedure sp_GetIdentity
go
create procedure sp_GetIdentity @strTable varchar(30)
as
declare @iIdentity int
select @iIdentity = iID
from #tblIdentity
where strTable = @strTable
return @iIdentity
go
drop table #tblIdentity
go
print ''
print 'Show the process in action'
print ''
create table #tblIdentity
(
iID int,
strTable varchar(30)
)
go
exec sp_Insert
go
print ' '
print 'After execution you can get a specific table value...'
print ' '
go
declare @iIdentity int
exec @iIdentity = sp_GetIdentity 'tblIdentity'
select 'tblIdenity' = @iIdentity
exec @iIdentity = sp_GetIdentity 'tblAudit'
select 'tblAudit' = @iIdentity
drop table #tblIdentity
go
Keywords: kbprb kbcode kbusage KB163446