52

I have a table with 50+ columns and I need to swap the order of the first two columns. What is the best way to accomplish this using Oracle? Assume the table name is ORDERDETAILS and as it is, the first two columns are ITEM_ID and ORDER_ID. Once the rename is complete, the table name should still be ORDERDETAILS but the first two columns will be ORDER_ID and ITEM_ID. FWIW, column types and the rest of the columns and their order is irelevent.

Correct me if I'm wrong, but I think the general steps are:

  1. Rename the existing table.
  2. Drop the primary key constraint.
  3. Re-create the table with the correct column order.
  4. List item
  5. Run INSERT INTO .. SELECT to move the data from temp to the table in step #3.
  6. Drop the temp table.

I have little experience with Oracle so perhaps I'm missing a step or two.

Does a primary key imply an index in Oracle? Does dropping the primary key also drop the index?

SQL examples are much appreciated.

EDIT: Un-sincere thanks to those who question why it needs done instead of providing help. To answer your question as to why it needs done: I'm following orders from someone else who says I need to do it this way and the order of the columns DOES matter. My thoughts/opinions on this are irrelevent.

Ryan Rodemoyer
  • 5,548
  • 12
  • 44
  • 54
  • I'm more of an MS SQL guy, but I can't think of any reason why you'd need to drop the PK. Your steps do not include one to create the temp table, unless you're referring to the renamed original table. –  Feb 09 '11 at 00:00
  • 2 - Drop all the constraints then 3a Add the constraints to the temp_table. Add in stats collection for the new table. Backup too. Not sure what you are doing with indexes either. – Gary Myers Feb 09 '11 at 00:04
  • Not sure I can think of any reason to need this, but if its just for the purpose of an index(?), you can just create the index on order_id, item_id instead of item_id, order_id. Taking a wild stab at your motivation for needing the table redefined. – tbone Feb 09 '11 at 12:32
  • 1
    For those asking why it's useful: I have an application that adds some metadata columns to existing tables. It's useful to all concerned if those columns are put at the front so that our added columns are immediately visible in sqldeveloper when the tables are viewed. – Mark Harrison Jul 06 '13 at 01:03
  • You can just use SELECT * instead of naming every bloody column when copying between two tables if the column order is the same. – Fax Nov 17 '16 at 11:40

5 Answers5

116

Since the release of Oracle 12c it is now easier to rearrange columns logically.

Oracle 12c added support for making columns invisible and that feature can be used to rearrange columns logically.

Quote from the documentation on invisible columns:

When you make an invisible column visible, the column is included in the table's column order as the last column.

Example

Create a table:

CREATE TABLE t (
    a INT,
    b INT,
    d INT,
    e INT
);

Add a column:

ALTER TABLE t ADD (c INT);

Move the column to the middle:

ALTER TABLE t MODIFY (d INVISIBLE, e INVISIBLE);
ALTER TABLE t MODIFY (d VISIBLE, e VISIBLE);

DESCRIBE t;

Name
----
A
B
C
D
E

Credits

I learned about this from an article by Tom Kyte on new features in Oracle 12c.

Jonas Meller
  • 1,816
  • 2
  • 14
  • 6
  • 3
    Thanks, this is exactly what I needed! Worked perfectly. – Kelly Cook Jul 02 '15 at 17:19
  • 1
    @Jonas, then we need to change order also in our query? – Asif Mushtaq Nov 29 '15 at 02:22
  • @UnKnown, the new order will be used by the values specified for the INSERT too (in case the column names are not specified). – Andrei Damian-Fekete Aug 07 '17 at 13:51
  • 1
    Here's a routine that uses invisible columns to allow you re-sequence the columns in any desired order. https://connor-mcdonald.com/2013/07/22/12c-invisible-columns/ – Connor McDonald Mar 06 '18 at 10:55
  • 3
    Note from the same article ..... "A positive side effect of using invisible columns is the ability to logically reorder the columns in a table. I stress that this will be a logical, not a physical, reordering of the columns." and "(Note that on disk the columns will really be stored as A, B, D, E, and C.) " – Rajeev Jun 20 '19 at 11:31
  • Still, this isn't a convenient solution, especially when you have tens of columns and there is a need to reorder the first few columns. – precise Nov 07 '19 at 08:15
  • Note that this will NOT change the physical storage order in the data blocks. Therefore if you are trying to mitigate row chaining block reads on tables with > 255 columns by moving rarely accessed columns to the end, this method will not help you. Only a real physical segment recreation (either manually or via dbms_redefinition) is going to truly reorder the columns in a complete way. The visible/invisible trick is just how the columns appear to SQL for SELECT * and INSERT VALUES without a column list, both of which should be discouraged as a programming practice anyway. – Paul W Apr 01 '23 at 16:53
21

Look at the package DBMS_Redefinition. It will rebuild the table with the new ordering. It can be done with the table online.

As Phil Brown noted, think carefully before doing this. However there is overhead in scanning the row for columns and moving data on update. Column ordering rules I use (in no particular order):

  • Group related columns together.
  • Not NULL columns before null-able columns.
  • Frequently searched un-indexed columns first.
  • Rarely filled null-able columns last.
  • Static columns first.
  • Updateable varchar columns later.
  • Indexed columns after other searchable columns.

These rules conflict and have not all been tested for performance on the latest release. Most have been tested in practice, but I didn't document the results. Placement options target one of three conflicting goals: easy to understand column placement; fast data retrieval; and minimal data movement on updates.

BillThor
  • 7,306
  • 1
  • 26
  • 19
  • 1
    Just remember ...Even DBMS_REDEFINITION is just, under the covers, creating a new table with a new column order, moving all the data from the old table to the new table, dropping the old table, and renaming the new table. – Carlos Quijano Apr 25 '15 at 15:51
  • Old topic, but I don't think that there has been a need for "Frequently searched un-indexed columns first." or "Indexed columns after other searchable columns." (which are very similar, in fact) since Oracle 9i or earlier, when there was a significant CPU overhead to locating rightmost columns. I certainly need to do that back then, but not since. – David Aldridge Apr 30 '15 at 19:17
  • @DavidAldridge Oracle have spent a lot of effort on improving table scan speeds, and have likely dropped the cost of scanning for rightmost columns significantly, I would expect there is still a cost to skipping columns. A definitive answer would require testing I don't have resources for. – BillThor May 01 '15 at 03:12
  • @BillThor "Anecdote is not data", but I built a heavily denormalised data mart many years ago with around 250 columns -- mostly number, some varchar2 scattered in -- and it was something I measured back then as being extremely significant when reading right-most columns whether for searching or just reading on full table scans. It was definitely worth going through the pain of physically reordering the table until that was suddenly fixed in some major version or other. 9i or 10g I think. Could probably find an asktom comment on it .. – David Aldridge May 01 '15 at 08:33
8

I followed the solution above from Jonas and it worked well until I needed to add a second column. What I found is that when making the columns visible again Oracle does not necessarily set them visible in the order listed in the statement.

To demonstrate this follow Jonas' example above. As he showed, once the steps are complete the table is in the order that you'd expect. Things then break down when you add another column as shown below:

Example (continued from Jonas'):

Add another column which is to be inserted before column C.

ALTER TABLE t ADD (b2 INT);

Use the technique demonstrated above to move the newly added B2 column before column C.

ALTER TABLE t MODIFY (c INVISIBLE, d INVISIBLE, e INVISIBLE);
ALTER TABLE t MODIFY (c VISIBLE, d VISIBLE, e VISIBLE);

DESCRIBE t;

Name
----
A
B
B2
D
E
C

As shown above column C has moved to the end. It seems that the ALTER TABLE statement above processed the columns in the order D, E, C rather than in the order specified in the statement (perhaps in physical table order). To ensure that the column is placed where desired it is necessary to make the columns visible one by one in the desired order.

ALTER TABLE t MODIFY (c INVISIBLE, d INVISIBLE, e INVISIBLE);
ALTER TABLE t MODIFY c VISIBLE;
ALTER TABLE t MODIFY d VISIBLE;
ALTER TABLE t MODIFY e VISIBLE;

DESCRIBE t;

Name
----
A
B
B2
C
D
E
ajz
  • 206
  • 4
  • 6
6

It's sad that Oracle doesn't allow this, I get asked to do this by developers all the time..

Here's a slightly dangerous, somewhat quick and dirty method:

  1. Ensure you have enough space to copy the Table
  2. Note any Constraints, Grants, Indexes, Synonyms, Triggers, um.. maybe some other stuff - that belongs to a Table - that I haven't thought about?
  3. CREATE TABLE table_right_columns AS SELECT column1 column3, column2 FROM table_wrong_columns; -- Notice how we correct the position of the columns :)
  4. DROP TABLE table_wrong_columns;
  5. 'ALTER TABLE table_right_columns RENAME TO table_wrong_columns;`
  6. Now the yucky part: recreate all those items you noted in step 2 above
  7. Check what code is now invalid, and recompile to check for errors

And next time you create a table, please consider the future requirements! ;)

Dominic Isaia
  • 127
  • 1
  • 9
grokster
  • 5,919
  • 1
  • 36
  • 22
  • How to preserve field comments: http://stackoverflow.com/questions/6910255/oracle-create-table-as-and-table-comments – Vadzim Nov 26 '15 at 13:52
  • Toad users should run Database->Optimize->Rebuild Table to generate almost all for the script for the above. – Unoembre Mar 15 '23 at 18:37
0

Use the View for your efforts in altering the position of the column: CREATE VIEW CORRECTED_POSITION AS SELECT co1_1, col_3, col_2 FROM UNORDERDED_POSITION should help.

This requests are made so some reports get produced where it is using SELECT * FROM [table_name]. Or, some business has a hierarchy approach of placing the information in order for better readability from the back end.

Thanks Dilip

dilip
  • 11
  • 1