SQL Server 2008.
I have a parent row with pk id 1. While blocking all other DB users (this is a cleanup operation so resource contention is not an issue), I would like to insert a new row, then take all of the child rows and change their fk column to the new row. With the below DDL for example, I would like to insert a new row and give all of the #chi.parid values a value of '3' so they would essentially now belong to the new row so the old one can be deleted.
Help!
create table #par ( parid int identity(1,1) , note varchar(8) )
create table #chi ( chiid int identity(1,1) , parid int , thing varchar(8) )
insert into #par values ( 'note1' )
insert into #par values ( 'note2' )
insert into #chi values ( 1 , 'a' )
insert into #chi values ( 1 , 'b' )
insert into #chi values ( 1 , 'c' )
Further to Kalium's solution, you could use the SCOPE_IDENTITY() function to retrieve the IDENTITY value of the last table insert.
This way you could code this as a Stored Procedure to do the whole thing:
And then simply:
I tend to shun surrogate keys in favour of natural keys or FKs; also, I would avoid
IDENTITY
for artificial identifiers. To be honest, I find myself in the minority and have often wondered myself how to achieve bulk inserts withIDENTITY
FKs.As per Alan Barker's answer, you can utilize
SCOPE_IDENTITY()
but only if you want to do this RBAR (row by agonizing row). You say, "this is a cleanup operation" so perhaps a procedural solution is acceptable.The way I've got around the problem myself is to manually generate a sequence of potential
IDENTITY
values (e.g. in a staging table) then useSET IDENTITY_INSERT TargetTable ON
to force the values in. Obviously, I need to ensure the proposed values will not actually be in use by the time theINSERT
occurs so all other users will still need to be blocked.A couple of things to watch. Sometimes the obligatory
UNIQUE
constraint on theIDENTITY
column is missing so you may need to check there are no collisions yourself. Also, I've found that the kind of person who likes surrogates can get a bit 'flustered' when the values aren't sequential (and in the positive range!) or, much worse, there is application logic that relies on a perfect sequence or has exposed theIDENTITY
values to the business (in which case 'faking' enterprise key values such as order numbers can fall fowl of real life auditors).EDIT: reading an answer to another SO question this morning reminded me about SQL Server 2008's
OUTPUT
clause to capture all the auto-generatedIDENTITY
values in a table e.g.Well in that case you could simply use a Cursor. Not the best for performance but looks like this is a downtime-clean up job anyway:
Thanks all for the input. It appears I "can't" do a set-based operation on this with SQL Svr 2008, so I did RBAR solution with a loop (I think it performs better than a cursor). Anyone who can comment on making this safer with try..catch or enlighten me more on doing this in a set, please comment. :)
Thanks.
I think you just want an update, such as :
FKeys shouldn't be an issue here.