I would like to have a column in my DB accessible via two column names temporarily.
Why? The column name was开发者_如何学C badly chosen, I would like to refactor it. As I want my webapp to remain stable while changing the column name, it would be good to
- have a (let's call it) symlink named better_column_name pointing to the column bad_column_name
- change the webapplication to use better_column_name
- drop the symlink and rename column to better_column_name
"Refactoring Databases" suggests to actually add a second column which is synchronized on commit in order to achieve this. I am just hoping that there might be an easier way with Oracle, with less work and less overhead.
As long as you have code that uses both column names, I don't see a way to get around the fact that you'll have two (real) columns in that table.
I would add the new column with the correct name and then create a trigger that checks which column has been modified and updates the "other" column correspondingly. So whatever is being updated, the value is synch'ed with the other column.
Once all the code that uses the old column has been migrated, remove the trigger and drop the old column.
Edit
The trigger would so do something like this:
CREATE OR REPLACE TRIGGER ...
...
UPDATE OF bad_column_name, better_column_name ON the_table
...
BEGIN
IF UPDATING ('BAD_COLUMN_NAME') THEN
:new.better_column_name = :new.bad_column_name
END IF;
IF UPDATING ('BETTER_COLUMN_NAME') THEN
:new.bad_column_name = :new.better_column_name
END IF;
END;
The order of the IF
statements controls which change has a "higher priority" in case someone updated both columns at the same time.
Rename the table:
alter table mytable rename to mytable_old;
Create a view with the original tablename with both bad_column_name and better_column_name that point to the same column (and of course all the other columns):
create or replace view mytable as
select column1
, column2
, ...
, bad_column_name
, bad_column_name better_column_name
from mytable_old
;
Since this view is updatable by default (I assume here that mytable has a primary key), you can insert/update/delete from the view and it doesn't matter if you use bad_column_name or better_column_name.
After the refactoring, drop the view and rename the table and column:
drop view mytable;
alter table mytable_old rename column bad_column_name to better_column_name;
alter table mytable_old rename to mytable;
The best solution to this is only available in Oracle 11g Release 2: Edition-based Redefinition. This really cool feature allows us to maintain different versions of database tables and PL/SQL code, using special triggers and views. Find out more.
Essentially this is Oracle's built-in implementation of @AHorseWithNoName's suggestion.
you can create a view for the table. And port your application to use that view instead of the table.
create table t (bad_name varchar2(10), c2 varchar2(10));
create view vt as select bad_name AS good_name, c2 from t;
insert into vt (good_name, c2) values ('blub', 'blob');
select * from t;
select * from vt;
If you're on 11g you could look at using a virtual column. I'd probably be tempted to change the order slightly; rename the real column and create the virtual one using the old (bad) name, which can then be dropped at leisure. You may be restricted, of course, and there may be implications on other objects being invalidated that make this order less suitable for you.
精彩评论