views:

370

answers:

2

I need to be able to change the primary keys in a table. The problem is, some of the keys will be changing to existing key values. E.g. record1.ID 3=>4 and record2.ID 4=>5. I need to keep these as primary keys as they are set as foreign keys (which cascade up update) Is there a reasonable way to accomplish this, or am I attempting sql heresey?

As for the why, I have data from one set of tables linked by this primary key that are getting inserted/updated into another set of similarly structured tables. The insertion is in parts, as it is part of a deduping process, and if I could simply update all of the tables that are to be inserted with the new primary key, life would be easier.

One solution is to start the indexing on the destination table higher than the incoming tables row count will ever reach (the incoming table gets re=indexed every time), but I'd still like to know if it is possible to do the above, otherwise.

TIA

+1  A: 

You are attempting sql heresy. I'm actually pretty open-minded and know a lot of times one must do things that seem crazy. It annoys me when people arrogantly answer with "you should do that differently", when they have know idea what the situation is. However I must tell you that you should do this differently. heh heh.

No, there is no way to do this elegantly with sql\DataAdapter. You could do it through ADO.NET with a series of t-sql commands. You have to, every time, turn on an identity-overwrite mode (set identity_insert theTable on), do your query where all the values on that table are incremented up one, and then turn of autonumber-overwrite mode. But then you would need to increment all the other tables that use this as a foreign key. But wait, it gets worse:

  • You would need to all this in a transaction, because you cannot have anything else happening to these tables during this time, and because if there was a failure you would most definitely need to rollback. This could be a good-size chunk of processing; your tables would be locked for a good bit.
  • If you have any foreign key constraints between these tables, you would need to turn them off before you do this, and re-implement them afterwards.
Patrick Karcher
The example given was for clarity. They are mapping, based on a unique column, to a different ID in the final table. I need the mapping to move related tables into their respective final tables with the correct foreign key. I can update the foreign key in each row in each table before inserting/updating them in their final tables, it just looked like I could cheat a little here.
Brian
Ah, okay. So, if the existing table's key is 45,987 and counting, can you have your 20,000 records your adding be mapped to 50,001 to 70,000? If there's a gap in the identity field, that's fine. (Or if it's not, you'd just need to update your mapping table at the last moment and stop new insertions from the normal process.) That seems like the most straightforward way to me, though I'm guessing I'm missing something. What am I missing?
Patrick Karcher
For new entities, this would work, but some of these entities correspond to existing records, and it's only their associated tables that may have data to update or insert. It's probably helpful to mention that both source and destination table sets are in the star pattern, with the central table consisting of the id and several uniquely identifying columns.
Brian
I am leaning towards just doing all the work right now in .net code (and moving to a temp mapping table and stored procedures later), but I was thinking that I'd get better performance if the id changes were handled by the foreign key cascade--as well as being lazier :-) Relying on indexing assumptions, as I suggested in the question, does not seem wise.
Brian
A: 

If you find yourself starting to think about update primary key values, alarm bells should start ringing. It may seem easier, but I'd class it as more of a hack than a solution. Personally, I'd be having a rethink and try to address the real problem - may seem harder now, but it will be much better to maintain and reduce potential horrible issues down the line.

AdaTheDev
The table the primary keys would be changing in is a work table. After a lot of processing, their rows get inserted (or updated) into the actual table. The rows in the actual table have, necessarily, different primary keys. Updating the primary keys in the central scratch table seemed an easy way to keep all the scratch tables linked by the central table's primary key together until their data is inserted into the final tables. It doesn't seem so much anymore.
Brian