tags:

views:

67

answers:

3

I have some Oracle tables that represent a parent-child relationship. They look something like this:

create table Parent (
    parent_id varchar2(20) not null primary key
);

create table Child (
    child_id number not null primary key,
    parent_id varchar2(20) not null,

    constraint fk_parent_id
        foreign key (parent_id)
        references Parent (parent_id)
);

This is a live database and its schema was designed long ago under the assumption that the parent_id field would be static and unchanging for a given record. Now the rules have changed and we really would like to change the value of parent_id for some records.

For example, I have these records:

Parent:

parent_id
---------
ABC123


Child:

child_id  parent_id
--------  ---------
1         ABC123
2         ABC123

And I want to modify ABC123 in these records in both tables to something else.

It's my understanding that one cannot write an Oracle update statement that will update both parent and child tables simultaneously, and given the FK constraint, I'm not sure how best to update my database. I am currently disabling the fk_parent_id constraint, updating each table independently, and then enabling the constraint.

Is there a better, single-step way to update this content?

+5  A: 

There are no cascading updates.

You could use a deferrable constraint.

Or, within a transaction:

  • Copy the Parent to a new row with the new key:

    INSERT INTO Parent (key, cols...) SELECT newkey, cols... FROM Parent WHERE key = oldkey

  • Assign all the children:

    UPDATE Child SET parent_id = newkey WHERE parent_id = oldkey

  • Delete the parent now that no one is referencing it:

    DELETE FROM Parent WHERE key = oldkey

See this link.

Cade Roux
+1: simple, efficient
Vincent Malgrat
@Vincent Malgrat - Your deleted answer is still a good one.
Cade Roux
@Cade Roux: I assumed that since it is an old schema modifying it might not be feasible (even if it would be the right thing to do)
Vincent Malgrat
There are about 600K rows in the parent and about 20 million rows in the child, and they're pretty wide records. I am also not sure right now how many processes depend on the current schema -- probably a couple dozen individual little utility scripts and two larger apps. My guess is that it might take a while to identify all of those, update the schema, and update the processes to expect the new schema. That's why I was hoping for a simple fix! :) I agree that your suggestion is a good one in general.
Chris Farmer
+3  A: 

Hi Chris,

If you find you need to update your primary key frequently, you may need to rethink your model and use a true immutable primary key. Use a column with a surrogate key that has no meaning (an incrementing identity column or a GUID) and store the value you want to update only in the parent table (so that when you need to update it you only have one row to modify).

Vincent Malgrat
Yeah, I agree. This was a schema that was initially provided by a vendor but that we've modified over time. If these new changes really prove troublesome, I think I will take the time to create some separate key that's not meaningful to the users of the data.
Chris Farmer
+2  A: 

Tom Kyte has provided a utility to implement "update cascade" functionality here.

Tony Andrews