views:

321

answers:

3

Our application uses an Oracle 10g database where several primary keys are exposed to the end user. Productcodes and such. Unfortunately it's to late to do anything with this, as there are tons of reports and custom scripts out there that we do not have control over. We can't redefine the primary keys or mess up the database structure.

Now some customer want to change some of the primary key values. What they initially wanted to call P23A1 should now be called CAT23MOD1 (not a real example, but you get my meaning.)

Is there an easy way to do this? I would prefer a script of some sort, that could be parametrized to fit other tables and keys, but external tools would be acceptable if no other way exists.

A: 

Oops. A little googling makes it appear that, inexplicably, Oracle does not implement ON UPDATE CASCADE, only ON DELETE CASCADE. To find workarounds google ORACLE ON UPDATE CASCADE. Here's a link on Creating A Cascade Update Set of Tables in Oracle.

Original answer:

If I understand correctly, you want to change the values of data in primary key columns, not the actual constraint names of the keys themselves.

If this is true it can most easily be accomplished redefining ALL the foreign keys that reference the affected primary key constraint as ON UPDATE CASCADE. This means that when you make a change to the primary key value, the engine will automatically update all related values in foreign key tables.

Be aware that if this results in a lot of changes it could be prohibitively expensive in a production system.

Larry Lustig
OMG Ponies
From the question, I assume that they're not in a position to disable the constraints, and it sounds like the end-user wants this capability on an ongoing basis rather than as a one-off job. I don't really see any option other than writing a pretty ugly trigger when updating the PK table.
Larry Lustig
@Larry: Yes, it's the values that should be changed.@OMG: Yes, very tedious :-( Do you have an entertaining way to do it? :-)
Svein Bringsli
I added a link to my answer. It might help. Doesn't looke "entertaining", exactly, but it is a script based approach that is adaptable to other key situations.
Larry Lustig
A: 

If you have to do this on a live system with no DDL changes to the tables involved, then I think your only option is to (for each value of the PK that needs to be changed):

  1. Insert into the parent table a copy of the row with the PK value replaced
  2. For each child table, update the FK value to the new PK value
  3. Delete the parent table row with the old PK value

If you have a list of parent tables and the PK values to be renamed, it shouldn't be too hard to write a procedure that does this - the information in USER_CONSTRAINTS can be used to get the FK-related tables for a given parent table.

dpbradley
+3  A: 

The problem is presumably with the foreign keys that reference the PK. You must define the foreign keys as "deferrable initially immediate", as described in this Tom Kyte article: http://www.oracle.com/technology/oramag/oracle/03-nov/o63asktom.html That lets you ...

  1. Defer the constraints
  2. Modify the parent value
  3. Modify the child values
  4. Commit the change

Simple.

David Aldridge