views:

44

answers:

3

I need to make a copy of a row in a table and also copy all the rows that link to it via its foreign key in other tables. And then copy all the rows that link to these rows.

The problem is when I make a copy of the row the key is going to change. How can I propagate these changes through the relationships between tables?

+1  A: 

A bit of a 'hack', but I often add a column 'copy_of_id', so that I can store the old id, and then copy over all rows in dependent tables for the newly created value.

It ain't pretty, but has advantages (human tracebility of what's happening, for instance).

You can also use a helper table for this, of course. Containing old ID and new ID columns. That will not pollute your primary table.

Tobiasopdenbrouw
This helped - I created a temporary helper table with tablename, oldid and new id.
DanDan
+1  A: 

You can write a stored procedure which implements all the copy logic.

Essentially:

  1. Insert copy row in master table - store new ID in variable
  2. Insert copy of each row in child tables, referencing FK in variable. Store the ID of the child row in variable2
  3. Insert new rows in tables dependent upon the child table, referencing the FK in variable2.

In short, write a stored proc that starts at the top and walks down as many tables as needed.

Wade Williams
I'm not sure how to handle the children of the child tables.
DanDan
We'd need more specifics to understand why they're a problem. A child of a child table is no different than the child of a master - it's just another level deep.
Wade Williams
If I do INSERT INTO ChildTable (SELECT (values) FROM ChildTable WHERE foreignkey = 1) - this may insert more than 1 child row. If I use SCOPE_IDENTITY I can only do further queries on the final row added.
DanDan
Then you need to use a cursor to get all the child rows and process them one at a time.
Wade Williams
So a cursor for every table I wish to copy?
DanDan
A cursor for every table which might return multiple rows. Probably easiest just to use a cursor for every table - it doesn't matter if on some tables it happens to contain only one row.
Wade Williams
Cursors combined with a temporary table (mapping old ids to new ids) combined with a stored procedure for every table that needed copied was the solution! Seems long winded but works very well.
DanDan
A: 

When creating your new "parent row", @@IDENTITY and SCOPE_IDENTITY() will contain the Id of your new header.

Then you can use them to create your "child rows", such as

INSERT INTO parent_table (parent_field1, parentfield2) VALUES('Some stuff', 'Other stuff');

INSERT INTO child_table (parent_id, other_field) VALUES(SCOPE_IDENTITY(), 'Etc.')

Take a look on MSDN for @@IDENTITY and SCOPE_IDENTITY() for code examples.

Danny T.
I thought of this, the children of the child_table cause problems though.
DanDan