Skip to Main Content
  • Questions
  • Maintain Tables - how to rename a column

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, Ahmad.

Asked: June 14, 2000 - 5:59 pm UTC

Last updated: June 15, 2005 - 9:41 am UTC

Version: 8.1.5

Viewed 1000+ times

You Asked

How I can rename a table column's?

and Tom said...

There are various ways. The way I prefer to do it is as such (it requires the least effort on my part and on the part of the database. it is the least error prone. it is easily undone):

o you have a table T with a column C. You would like C to be called NewName from now on:

1) rename t to t_table
2) create view t as select ..., C newName, ... from T
3) select 'grant ' || privelege || ' on T to ' || grantee||';'
from user_tab__privs
where table_name = 'T_TABLE';

spool and save the results of that query, run those grants
4) select 'revoke ' || privelege || ' on T_TABLE from ' ||
grantee||';'
from user_tab__privs
where table_name = 'T_TABLE';

spool and save the results of that query, run those revokes

As far as anyone is concerned, the column has been renamed with minimal IO and no impact on future performance.



o you have the same situation as above. You have Oracle8i or up. you could:

1) alter table T add newName <datatype>;
2) update t set NewName = C, C = Null;
3) alter table T set unused column C; -- flag delete, since
C is null everywhere, no real need to rewrite the entire
table by dropping C, flag deletion is more then sufficient


o you have the same situation. You have Oracle8.0 and before. Your options (other then the view) are somewhat limited. You can create a copy of the table as select (renaming the column on the way into the new table), dropping the original table and then renaming the copy back -- but you must restore the grants, triggers, constraints, etc. If you take an export of the table with rows=N before you do the copy and then import the table AFTER you rename the copy, it'll get most of that stuff back for you. Here is an full annotated example using that method:

Here is our table. Our goal will be ultimately to rename Y to "newName"

ops$tkyte@8i> create table t
2 ( x int primary key,
3 y int check ( y > 0 ) );
Table created.

ops$tkyte@8i>
ops$tkyte@8i> create or replace trigger t_trigger
2 before insert on t for each row
3 begin
4 :new.y := :new.y+1;
5 end;
6 /

Trigger created.

ops$tkyte@8i> grant select on t to connect;
Grant succeeded.

ops$tkyte@8i> grant insert on t to resource;
Grant succeeded.

ops$tkyte@8i> create index y_idx on t(y);
Index created.

ops$tkyte@8i> select object_name, object_type
2 from user_objects
3 union all
4 select constraint_name, 'CONSTRAINT'
5 from user_constraints
6 union all
7 select privilege, grantee
8 from user_tab_privs
9 /

OBJECT_NAME OBJECT_TYPE
------------------------------ ------------------------------
SYS_C0025444 INDEX
T TABLE
T_TRIGGER TRIGGER
Y_IDX INDEX
SYS_C0025443 CONSTRAINT
SYS_C0025444 CONSTRAINT
SELECT CONNECT
INSERT RESOURCE

8 rows selected.

So, there are the things about T we need. We have some indexes, triggers, constraints, grants...

ops$tkyte@8i> host exp userid=/ tables=t rows=n

Export: Release 8.1.5.0.0 - Production on Thu Jun 15 09:13:11 2000

(c) Copyright 1999 Oracle Corporation. All rights reserved.


Connected to: Oracle8i Enterprise Edition Release 8.1.5.0.0 - Production
With the Partitioning and Java options
PL/SQL Release 8.1.5.0.0 - Production
Export done in US7ASCII character set and US7ASCII NCHAR character set
Note: table data (rows) will not be exported

About to export specified tables via Conventional Path ...
. . exporting table T
Export terminated successfully without warnings.

That export got what we needed structurally about T. It extracted only DDL, no data

ops$tkyte@8i> create table t2 as select x x, y newName from t;
Table created.

That "renamed" the column, we can now:


ops$tkyte@8i> drop table t;
Table dropped.

ops$tkyte@8i> rename t2 to t;
Table renamed.

So, effectively the column has been renamed, now we need to get back all of the "stuff" about T from above (constraints, grants, etc)

ops$tkyte@8i> host imp userid=/ full=y ignore=y

Import: Release 8.1.5.0.0 - Production on Thu Jun 15 09:13:15 2000

(c) Copyright 1999 Oracle Corporation. All rights reserved.


Connected to: Oracle8i Enterprise Edition Release 8.1.5.0.0 - Production
With the Partitioning and Java options
PL/SQL Release 8.1.5.0.0 - Production

Export file created by EXPORT:V08.01.05 via conventional path
import done in US7ASCII character set and US7ASCII NCHAR character set
. importing OPS$TKYTE's objects into OPS$TKYTE
IMP-00017: following statement failed with ORACLE error 904:
"CREATE INDEX "Y_IDX" ON "T" ("Y" ) PCTFREE 10 INITRANS 2 MAXTRANS 255 STOR"
"AGE(INITIAL 524288) TABLESPACE "UTILS" LOGGING"
IMP-00003: ORACLE error 904 encountered
ORA-00904: invalid column name
IMP-00017: following statement failed with ORACLE error 904:
"ALTER TABLE "T" ADD CHECK ( y > 0 ) ENABLE"
IMP-00003: ORACLE error 904 encountered
ORA-00904: invalid column name
IMP-00041: Warning: object created with compilation warnings
"CREATE TRIGGER "OPS$TKYTE".t_trigger"
"before insert on t for each row"
""
"begin"
" :new.y := :new.y+1;"
"end;"
Import terminated successfully with warnings.

So, according to the import,

o the INDEX Y_idx failed (we need to create that, convienently, the create index we need to modify is right there...).

o the check constraint failed, again we have the statement we need to fix right there

o the create trigger failed as well -- we'll have to fix that one up



ops$tkyte@8i> select object_name, object_type
2 from user_objects
3 union all
4 select constraint_name, 'CONSTRAINT'
5 from user_constraints
6 union all
7 select privilege, grantee
8 from user_tab_privs
9 /

OBJECT_NAME OBJECT_TYPE
------------------------------ ------------------------------
SYS_C0025445 INDEX
T TABLE
T_TRIGGER TRIGGER
SYS_C0025445 CONSTRAINT
SELECT CONNECT
INSERT RESOURCE

6 rows selected.

ops$tkyte@8i>

but as you can see -- all of the other things (grants and such) are in place for us.

Rating

  (4 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Lilian An from Wilmington DE

Lilian An, June 13, 2001 - 12:42 pm UTC

very clear and detail explanation and example.

Waiting

Jack Mulhollan, June 12, 2002 - 2:15 pm UTC

Tom, did you ever create a table and later realize that one of the column names you chose was not ideal? So did I. So did everyone else who ever created a table.

Your answer demonstrates that changing a column name in Oracle is truely a pain.

The view solution is simple enough. Here's the problem with it: It adds one more layer of complexity, one more source of confusion, one more thing to document, one more thing to remember. In my experience, these little things add up over time. Eventually you end up with a database that only the designer understands. Unfortunately, she got a better job at Initec two years ago.

Here's the solution I prefer:

alter table T rename column C to NewName;

I try this from time to time just to see if God has come down and implemented it in Oracle. He hasn't yet. I'm still waiting. I think he'll fix it eventually, or someone at Oracle will get a spare 5 minutes.



Tom Kyte
June 13, 2002 - 7:37 am UTC

Well, here is my take on this:

If you didn't name the column correctly and you are going to correct it, you must not have any code that accessess it -- hence this is a BRAND SPANKING NEW TABLE and is most likely EMPTY.  drop it, recreate it.

Also, some people use views as their only access path -- no table access.  This gives them the flexibility to 

o hide columns as new ones are added to the table, protecting existing applications (they'll create a new view that exposes these new columns for new applications)

o lets you "rename" a column easily (as it is just a view)

among other nice abstractions.

(and to think that it takes a spare "5 minutes....." hmmm)

However...


In Oracle9iR2:

ops$tkyte@ORA920> desc t
 Name                                Null?    Type
 ----------------------------------- -------- ------------------------
 OWNER                               NOT NULL VARCHAR2(30)
 OBJECT_NAME                         NOT NULL VARCHAR2(30)
 SUBOBJECT_NAME                               VARCHAR2(30)
 OBJECT_ID                           NOT NULL NUMBER
 DATA_OBJECT_ID                               NUMBER
 OBJECT_TYPE                                  VARCHAR2(18)
 CREATED                             NOT NULL DATE
 LAST_DDL_TIME                       NOT NULL DATE
 TIMESTAMP                                    VARCHAR2(19)
 STATUS                                       VARCHAR2(7)
 TEMPORARY                                    VARCHAR2(1)
 GENERATED                                    VARCHAR2(1)
 SECONDARY                                    VARCHAR2(1)

ops$tkyte@ORA920> <b>alter table t rename column owner to ownerX;</b>

Table altered.

ops$tkyte@ORA920> desc t;
 Name                                Null?    Type
 ----------------------------------- -------- ------------------------
 OWNERX                              NOT NULL VARCHAR2(30)
 OBJECT_NAME                         NOT NULL VARCHAR2(30)
 SUBOBJECT_NAME                               VARCHAR2(30)
 OBJECT_ID                           NOT NULL NUMBER
 DATA_OBJECT_ID                               NUMBER
 OBJECT_TYPE                                  VARCHAR2(18)
 CREATED                             NOT NULL DATE
 LAST_DDL_TIME                       NOT NULL DATE
 TIMESTAMP                                    VARCHAR2(19)
 STATUS                                       VARCHAR2(7)
 TEMPORARY                                    VARCHAR2(1)
 GENERATED                                    VARCHAR2(1)
 SECONDARY                                    VARCHAR2(1) 

Difference

Fiza, August 08, 2002 - 10:11 am UTC

Hi i read docs related to index organized table and regular table but still not clear is any of can help me...Thanks

Tom Kyte
August 08, 2002 - 1:03 pm UTC

Hmm, and this has to do with renaming a column how?

If you have my expert one on one book -- i cover it in detail there in the chapter on tables.

If you want to read what I've written about them in other questions, just search for

index organized tables

you'll get some meaningful hits there.

Mehul, June 15, 2005 - 4:12 am UTC

Here it is ok we can do renaming the column but in oracle 92 now onward it is now command to rename the column but i need to know why and what is the real reason to change the column name and why oracle has given this facility in oracle 9.2 is there any reasonable reason to rename a column .

Tom Kyte
June 15, 2005 - 9:41 am UTC

because people kept asking for it.

More to Explore

VLDB

If you are new to partitioning, check out Connor McDonald's introduction series here.

VLDB

Documentation set on VLDB and Partitioning.