My problem is this: I have data in a couple of temporary tables including relations (one table referencing records from another table by using temporary keys).
Next, I would like to insert the data from the temp tables to my productive tables which have the same structure but their own identity keys. Hence, I need to translate the 'temporary' keys to regular identity keys in my productive tables.
This is even more difficult because the system is highly concurrent, i.e. multiple sessions may try to insert
data that way simultaneously.
So far we were running the following solution, using a combination of identity_insert and ident_current:
create table doc(id int identity primary key, number varchar(100)) create table pos (id int identity primary key, docid int references doc(id), qty int) create table #doc(idx int, number varchar(100)) create table #pos (docidx int, qty int) insert #doc select 1, 'D1' insert #doc select 2, 'D2' insert #pos select 1, 10 insert #pos select 1, 12 insert #pos select 2, 32 insert #pos select 2, 9 declare @docids table(ID int) set identity_insert doc on insert doc (id,number) output inserted.ID into @docids select ident_current('doc')+idx,number from #doc set identity_insert doc off -- Since scope_identity() is not reliable, we get the inserted identity values this way: declare @docID int = (select min(ID) from @docids) insert pos (docid,qty) select @docID+docidx-1, qty from #pos
Since the request to ident_current() is located directly in the insert statement, we always have an implicit transaction which should be thread safe to a certain extend.
We never had a problem with this solution for years until recently when we were running in occasional primary key violations. After some reasearch it turned out, that there were concurrent sessions trying to insert records in this way.
Does anybody have an explanation for the primary key violations or an alternative solution for the problem?
Thank you
David