37

I have a specific scenario where i have to insert two new columns in an existing table in Oracle. I can not do the dropping and recreating the table. So can it be achieved by any means??

Jon Heller
  • 34,999
  • 6
  • 74
  • 132
Amit
  • 623
  • 2
  • 8
  • 18
  • 4
    In 12c there is a trick to do it: http://tkyte.blogspot.com.au/2013/07/12c-silly-little-trick-with-invisibility.html (Note, however, there is no logical reason to change the column order.) – Jeffrey Kemp Jul 03 '13 at 00:54
  • 1
    Wouldn't you want to add the columns which are most likely to be null at the end of the table to save space? See https://community.oracle.com/thread/855964 – Akshay Gehi Dec 29 '16 at 12:26
  • 2
    @JeffreyKemp there is a possible logical reason: convenience for the developer :-) you might want to see the most relevant columns in the viewport without horizontal scrolling, using a tool like Oracle SQL Developer which issues `SELECT *` statements by default. – dr fu manchu Jan 02 '19 at 14:16
  • 1
    @JeffreyKemp the tkyte blog is not (@2019-06-10) generally viewable; it comes up with 'This blog is open to invited readers only'. As for column order, I would prefer not to see the following column order: Name, Addr1, Addr2, DoB, Phone, Email, Dept, Addr3 – brewmanz Jun 09 '19 at 19:50
  • 1
    @brewmanz, refer to: https://stackoverflow.com/a/54007750/103295 – Jeffrey Kemp Jun 10 '19 at 00:30

4 Answers4

28

Amit-

I don't believe you can add a column anywhere but at the end of the table once the table is created. One solution might be to try this:

CREATE TABLE MY_TEMP_TABLE AS
SELECT *
FROM TABLE_TO_CHANGE;

Drop the table you want to add columns to:

DROP TABLE TABLE_TO_CHANGE;

It's at the point you could rebuild the existing table from scratch adding in the columns where you wish. Let's assume for this exercise you want to add the columns named "COL2 and COL3".

Now insert the data back into the new table:

INSERT INTO TABLE_TO_CHANGE (COL1, COL2, COL3, COL4) 
SELECT COL1, 'Foo', 'Bar', COL4
FROM MY_TEMP_TABLE;

When the data is inserted into your "new-old" table, you can drop the temp table.

DROP TABLE MY_TEMP_TABLE;

This is often what I do when I want to add columns in a specific location. Obviously if this is a production on-line system, then it's probably not practical, but just one potential idea.

-CJ

CJ Travis
  • 536
  • 4
  • 5
19

In 12c you can make use of the fact that columns which are set from invisible to visible are displayed as the last column of the table: Tips and Tricks: Invisible Columns in Oracle Database 12c

Maybe that is the 'trick' @jeffrey-kemp was talking about in his comment, but the link there does not work anymore.

Example:

ALTER TABLE my_tab ADD (col_3 NUMBER(10));
ALTER TABLE my_tab MODIFY (
  col_1 invisible,
  col_2 invisible
);
ALTER TABLE my_tab MODIFY (
  col_1 visible,
  col_2 visible
);

Now col_3 would be displayed first in a SELECT * FROM my_tab statement.

Note: This does not change the physical order of the columns on disk, but in most cases that is not what you want to do anyway. If you really want to change the physical order, you can use the DBMS_REDEFINITION package.

MaxU - stand with Ukraine
  • 205,989
  • 36
  • 386
  • 419
dr fu manchu
  • 618
  • 5
  • 10
7

Although this is somewhat old I would like to add a slightly improved version that really changes column order. Here are the steps (assuming we have a table TAB1 with columns COL1, COL2, COL3):

  1. Add new column to table TAB1:
alter table TAB1 add (NEW_COL number);
  1. "Copy" table to temp name while changing the column order AND rename the new column:
create table tempTAB1 as select NEW_COL as COL0, COL1, COL2, COL3 from TAB1;
  1. drop existing table:
drop table TAB1;
  1. rename temp tablename to just dropped tablename:
rename tempTAB1 to TAB1;
Gerd
  • 71
  • 1
  • 1
5

You (still) can not choose the position of the column using ALTER TABLE: it can only be added to the end of the table. You can obviously select the columns in any order you want, so unless you are using SELECT * FROM column order shouldn't be a big deal.

If you really must have them in a particular order and you can't drop and recreate the table, then you might be able to drop and recreate columns instead:-

First copy the table

CREATE TABLE my_tab_temp AS SELECT * FROM my_tab;

Then drop columns that you want to be after the column you will insert

ALTER TABLE my_tab DROP COLUMN three;

Now add the new column (two in this example) and the ones you removed.

ALTER TABLE my_tab ADD (two NUMBER(2), three NUMBER(10));

Lastly add back the data for the re-created columns

UPDATE my_tab SET my_tab.three = (SELECT my_tab_temp.three FROM my_tab_temp WHERE my_tab.one = my_tab_temp.one);

Obviously your update will most likely be more complex and you'll have to handle indexes and constraints and won't be able to use this in some cases (LOB columns etc). Plus this is a pretty hideous way to do this - but the table will always exist and you'll end up with the columns in a order you want. But does column order really matter that much?