views:

215

answers:

3

I've got a table that people have been inserting into getting the primary key by doing a

SELECT max(id)+1 from table_a;

I want to add some records to that table using a INSERT INTO table_a SELECT ... FROM table_b, table_c ... simple SQL script, and I'm wondering how to generate the primary keys. My first thought was to create a temporary sequence, but Oracle evidently doesn't have a select setval to set the first value. So how do I get the current value of max(id)+1 to set the "start with" parameter to my sequence?

I found something on-line that I thought would work:

COLUMN S new_value st select max(id)+1 S from  table_a;
CREATE SEQUENCE cra_seq start with &st;

But it doesn't actually use st in the CREATE SEQUENCE but instead prompts me to enter it, which isn't what I need.

A: 

You can use the row_number analytical function to generate row numbers (1 through N).

Before you do the insert, get the max id that is in the table, and then add the row number to that max and it will populate your table correctly.

casperOne
I have no idea how to "get the max id" in a sql script.
Paul Tomblin
@Paul Tomblin: I suggest you look at the "max" function in SQL.
casperOne
I know how to display a max id, I don't know how to use it the way you suggest. It seems like you're talking about selecting it into a variable, and I have no idea how you do that in a sql script.
Paul Tomblin
+3  A: 

Is this something like what you want?

  1  declare
  2    id  integer;
  3  begin
  4    select max(rownum)+1 into id from dual;
  5    execute immediate 'create sequence myseq start with '||TO_CHAR(id);
  6* end;
  7  /
Dave Costa
That works as far as it goes, but the very next line now SQL*Developer is complaining that the line beginning with "INSERT" is in error, even though it's fine if I execute that line on its own.
Paul Tomblin
Error report:ORA-06550: line 8, column 1:PLS-00103: Encountered the symbol "INSERT" 06550. 00000 - "line %s, column %s:\n%s"*Cause: Usually a PL/SQL compilation error.*Action:
Paul Tomblin
I think you need to create the sequence before you compile the procedure, then inside drop and recreate it.
DCookie
@DCookie, that didn't help.
Paul Tomblin
Is your insert inside the procedure?
DCookie
No, the insert it after the `end;`
Paul Tomblin
Then I think you're likely missing the "/" after your procedure.
DCookie
Hey, adding the / fixed it! I have no idea why, but it works.
Paul Tomblin
The "/" tells the database to compile and execute the procedure - up to that point it's simply being edited.
DCookie
+1  A: 

Couldn't you use the row_number function like so:

Insert Destination( Id, ...)
Select row_number() over( order by TableA.Col1... ) + MaxDestination.MaxId + 1 Num
 , ....
From TableA, TableB,...
 Cross Join ( Select Max(Id) MaxId From Destination ) MaxDestination
Thomas
What's the purpose of the `order by col1, col2` there?
Paul Tomblin
Shoot, now it's telling "SQL command not properly ended". I've got `insert into table_a (id, a, b, c) select row_number() over (order by b) + maxcra.maxid+1, d, e FROM table_b cross join (select max(id) as maxid from table_a) as maxcra where table_b.b = 'FOO';`
Paul Tomblin
Col1, Col2 represent placeholders for column.s The order by clause simply tells the system how to order the results to determine the row_number. If you had a column called Name and wanted the lowest sorted Name to have the lowest row number, you would use Order By Name. I think you need to change "order by b" to "order by table_b.b" however, I'll look at further here.
Thomas
I've posted a correction. In short, Oracle did not like the use of the "as" keyword.
Thomas