Stacy, tom kyte's definitive oracle book references unwise java programmers who adopt the max(id+1) plan.
it is not scalable, requires locking, forces full scans of the entire id column (if it is indexed) or full table scans if it is not. I am sure I am missing many of the myriad reasons he discusses why this is such a bad idea, especially since oracle provides sequences. There are numerous reasons not to use the strategy you have. gaps are the least of your concern. ever consider having two items with the same id? that is what would happen under your approach. we both do that query before an insert or commit of the insert takes place, and we both get the same number back from the database. unless you are locking the table of course and then... pasting from asktom.oracle.com: http://asktom.oracle.com/pls/ask/f?p=4950:8:::::F4950_P8_DISPLAYID:4343369880986 another great gap free article: http://asktom.oracle.com/pls/ask/f?p=4950:8:::::F4950_P8_DISPLAYID:1508205334476 do a search for gap free on this site for many more explanations of why this is no good. people try to defend it. they use a different approach than you, since i don't believe the dbi can retrieve values from an update .... returning statement (which at least doesn't have to do a full table scan). ******************(from tom kyte)************* well, if you use a gap free approach -- you know what'll happen in this case? NO ONE ELSE IN YOUR ENTIRE SYSTEM WILL BE ABLE TO WORK, that is what. Why? cause this session with uncommitted data will have the id generating table locked. Sigh, I hesitate to show you this, but here goes. Gap free, non-concurrent, highly NON-scalable: ops$[EMAIL PROTECTED]> create table ids ( name varchar2(30), id number ); Table created. ops$[EMAIL PROTECTED]> ops$[EMAIL PROTECTED]> create or replace function get_nextval( p_name in varchar2 ) return number 2 as 3 l_id number; 4 begin 5 update ids set id = id+1 where name = upper(p_name) 6 returning id into l_id; 7 8 if ( sql%rowcount = 0 ) 9 then 10 raise_application_error( -20001, 'No such id name ' || p_name ); 11 end if; 12 return l_id; 13 end; 14 / Function created. ops$[EMAIL PROTECTED]> ops$[EMAIL PROTECTED]> exec dbms_output.put_line( get_nextval( 'foo' ) ) BEGIN dbms_output.put_line( get_nextval( 'foo' ) ); END; * ERROR at line 1: ORA-20001: No such id name foo ORA-06512: at "OPS$TKYTE.GET_NEXTVAL", line 10 ORA-06512: at line 1 ops$[EMAIL PROTECTED]> ops$[EMAIL PROTECTED]> insert into ids values ( 'FOO', 0 ); 1 row created. ops$[EMAIL PROTECTED]> exec dbms_output.put_line( get_nextval( 'foo' ) ) 1 PL/SQL procedure successfully completed. ops$[EMAIL PROTECTED]> exec dbms_output.put_line( get_nextval( 'foo' ) ) 2 PL/SQL procedure successfully completed. Now, when you want to reset, just update ids set id = 0 where name = 'whatever'. To get an autoincrement column, I would: create table T ( x int primary key, .... ); create sequence t_seq; create trigger t_trigger before insert on T for each row begin if ( :new.x is null ) then select t_seq.nextval into :new.x from dual; end if; end; / to automatically populate when a value for X was not supplied (allowing me to easily override the "auto" part of it) or I would: create table T ( x int primary key, .... ); create sequence t_seq; and then: insert into t ( x, ... ) values ( t_seq.nextval, .... ); The nice thing about sequences is when you are populating a parent/child table -- you have immediate access to t_seq.CURRVAL which returns the value of the last NEXTVAL you selected. __________________________________________________ Do You Yahoo!? Sign up for SBC Yahoo! Dial - First Month Free http://sbc.yahoo.com