0

I'm updating a table that was originally poorly designed. The table currently has a primary key that is the name of the vendor. This serves as a foreign key to many other tables. This has led to issues with the Vendor name initially being entered incorrectly or with typos that need to be fixed. Since it's the foreign key to relationships, this is more complicated than it's worth.

Current Schema: Vendor_name(pk) Vendor_contact comments

Desired Schema: id(pk) Vendor_name Vendor_contact comments

I want to update the primary key to be an auto-generated numeric key. The vendor name field needs to persist but no longer be the key. I'll also need to update the value of the foreign key on other tables and on join tables.

Is the best way to do this to create a new numeric id column on my Vendor table, crosswalk the id to vendor names and add a new foreign key with the new id as the foreign key, drop the foreign key of vendor name on those tables (per this post), and then somehow mark the id as the primary key and unmark the vendor name?

Or is there a more streamlined way of doing this that isn't so broken out?

It's important to note that only 5 users can access this table so I can easily shut them out for a period of time while these updates are made - that's not an issue.

I'm working with SQLDeveloper and Python/Django.

Community
  • 1
  • 1
rockman
  • 23
  • 5

2 Answers2

0

I would do it this way:

  • create your new sequence
  • create table temp as select your_sequence.nextval,vendor_name, vendor_contact, comments from vendor.
  • rename the original table to something like vendor_old
  • add the primary key and other constraints to the new table
  • rename the new table to the old name

Testing is essential and you must ensure no one is working on the database except you when this is done.

kevinskio
  • 4,431
  • 1
  • 22
  • 36
0

The biggest problem you have is all the application code which references VENDOR_NAME in the dependent tables. Not just using it to join to the parent table, but also relying on it to display the name without joining to VENDOR.

So, although having a natural key as a foreign key is a PITN, changing this situation is likely to generate a whole lot of work, with a marginal overall benefit. Be sure to get buy-in from all the stakeholders before starting out.

The way I would approach it is this:

  1. Do a really thorough impact analysis
  2. Ensure you have complete regression tests for all the functions which rely on the Vendor data
  3. Create VENDOR_ID as a unique key on VENDOR
  4. Add VENDOR_ID to all the dependent tables
  5. Create a second foreign on all the dependent tables referencing VENDOR_ID
  6. Ensure that the VENDOR_ID is populated whenever the VENDOR_NAME is.

That last point can be tackled by either fix the insert and update statements on the dependent tables, or with triggers. Which approach you take will determine on your application design and also the number of tables involved. Obviously you want to avoid the performance hit of all those triggers if you can.

At this point you have an infrastructure which will support the new primary key but which still uses the old one. Why would you want to do this? Because you could go into Production like this without changing the application code. It gives you the option to move the application code to use VENDOR_ID across a broader time frame. Obviously, if developers have been keen on coding SELECT * FROM you will have issues that need addressing immediately.

Once you've fixed all the code you can drop VENDOR_NAME from all the dependent tables, and switch VENDOR_NAME to unique key and VENDOR_ID to primary key on the master table.

If you're on 11g you should check out Edition-Based Redefinition. It's designed to make this sort of exercise an awful lot easier. Find out more.

APC
  • 144,005
  • 19
  • 170
  • 281