views:

200

answers:

3

I need to copy some data from one table to another in Oracle, while generating incremental values for a numeric column in the new table. This is a once-only exercise with a trivial number of rows (100).

I have an adequate solution to this problem but I'm curious to know if there is a more elegant way.

I'm doing it with a temporary sequence, like so:

CREATE SEQUENCE temp_seq
    START WITH 1;

INSERT INTO new_table (new_col, copied_col1, copied_col2)
    SELECT temp_seq.NEXTVAL, o.*
      FROM (SELECT old_col1, old_col2
              FROM old_table,
          ORDER BY old_col1) o;

DROP SEQUENCE temp_seq;

Is there way to do with without creating the sequence or any other temporary object? Specifically, can this be done with a self-contained INSERT SELECT statement?

Please consider a trigger to be a non-option.

MORE INFO: I would like to control the order that the new rows are inserted, and it won't be the same order they were created in the old table (note I've added the ORDER BY clause above). But I still want my new sequential column to start from 1.

There are similar questions, but I believe the specifics of my question are original to SO.

A: 

I think is imposible, that is the only way to do that.

juanp
-1, not true...
DCookie
"the man who says something is impossible should not interrupt the man who is doing it" :)
Jeffrey Kemp
+4  A: 

You can use ROWNUM. This pseudo-column numbers the rows in your result:

Insert Into new_table (new_col, copied_col1, copied_col2)
    Select Rownum, old_col1, old_col2
    From old_table;

If you want your records to be sorted, you need to use a sub-query:

Insert Into new_table (new_col, copied_col1, copied_col2)
    Select Rownum, old_col1, old_col2
    From (
        Select old_col1, old_col2
        From old_table
        Order By old_col1
    );
Peter Lang
Peter, see the additional criteria I've added the question. This method seems to insert the rows in the order they were created in the old table, but I'd like to enforce my own order. If not for this requirement, your method would be perfect. Any ideas?
Charles
@Charles: My query actually does not sort the rows, so it is likely that they are inserted in the order they were created (but not guaranteed). Have you tried to apply your `ORDER BY` to my query? I would expect this to work.
Peter Lang
Then add the ORDER BY to the select statement. That should get you what you want. ROWNUM simply generates a sequence number for the records in the order retrieved.
DCookie
Okay guys, you're half right. The problem is that the ROWNUM is applied BEFORE the ORDER BY. The fix is to use a subquery. Just replace temp_seq.NEXTVAL in my solution with ROWNUM. Voila! Peter, update your answer thusly and I'll mark it accepted. Thanks!
Charles
A: 

Why don't you define the column new_col as primary_key or unique and mark it as autoincrement? This way each insert will get the next higher "count".

I'm not pretty familiar with oracle, but i would bet there is a built in autoincrement function.

Philipp Andre
@Philipp Andre: There is no *autoincrement function*, Oracle uses sequences instead.
Peter Lang
@Peter Lang: Really? That surprises me, but its long ago i've played with oracle. Nice to know. Thank you!
Philipp Andre
That's what I'd have done in SQL Server. :)
Charles