Skip to Main Content
  • Questions
  • How can we skip existing values while inserting with sequence to id column(unique)

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question.

Asked: July 12, 2016 - 2:27 pm UTC

Last updated: July 15, 2016 - 9:07 am UTC

Version: 11

Viewed 1000+ times

You Asked

Hi Tom,

Can you please let me know best possible way for below scenario to skip existing value while loading through sequence

Table Structure:
Tem_seq_check(id number(3) unique,name varchar2(5));

Tem_name(name varchar2(5)).

I will insert id column with sequence:
CREATE SEQUENCE tem_seq_check_id
INCREMENT BY 1
MINVALUE 1
MAXVALUE 15
CYCLE
CACHE 1;

Insert into Tem_seq_check select tem_seq_check_id.next_val,name from tem_name:
Now table is having below data:

Id name
1 a
2 b
3 c
4 d
5 g
6 j
7 t
8 h
9 w
10 e
11 q
12 o
13 y
14 y
15 d
Now I will delete data from above table for id’s 4&5
For next insert how can I skip sequence without generating 1,2,3 and it has to generate id as 4.

and Chris said...

What exactly is your business requirement here? Are you being asked to ensure there's no gaps? Or do you have a table with 15 rows (or other fixed number) and you always need the numbers from 1-N?

In either case, instead of trying to "loop through the sequence" you're probably better off:

- Generating all the numbers in your range
- Excluding from this the numbers in your table
- Inserting the result

For example:
create table t as
  select rownum x, chr(rownum+64) y from dual connect by level <= 15;

delete t
where  x in (4, 5);

insert into t 
with rws as (
  select rownum x, chr(rownum+79) y from dual connect by level <= 15
)
  select x, y from rws
  where  not exists (select * from t where rws.x = t.x);

select * from t;

X   Y  
1   A  
2   B  
3   C  
6   F  
7   G  
8   H  
9   I  
10  J  
11  K  
12  L  
13  M  
14  N  
15  O  
5   T  
4   S


If for some reason you must use the sequence, then you could do something like:

- Find the first value with a gap after it
- Fetch values from the sequence until you hit this

create sequence s start with 1 increment by 1 maxvalue 15 cycle cache 2;

select s.nextval from t
where  rownum <= 10;

NEXTVAL  
1        
2        
3        
4        
5        
6        
7        
8        
9        
10

delete t
where  x in (4, 5);

declare
 mx int;
 seq_val int;
begin
  select max(x) into mx from t
  start with x = 1
  connect by prior x = x - 1;
  
  loop
    seq_val := s.nextval;
    exit when seq_val = mx;
  end loop;
end;
/

insert into t values (s.nextval, 'Z');

select * from t;

X   Y  
1   A  
2   B  
3   C  
6   F  
7   G  
8   H  
9   I  
10  J  
11  K  
12  L  
13  M  
14  N  
15  O  
4   Z

Rating

  (1 rating)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Thanks for your time and help

Ram, July 15, 2016 - 7:49 am UTC

Requirement is we have one table having id as unique column,the will start from 1 at some point, therefore an insert will fail with unique constraints error.
Connor McDonald
July 15, 2016 - 9:07 am UTC

Np gaps in a transactional system is a really really really bad idea.

Think about how this would have to work. To find a gap, you need to make sure no-one is filling that gap right at this moment. So your logic ends up being:

a- lock the table
b- scan the table looking for gaps
c- fill the gap
d- commit

That means only 1 person can do a transaction at a time. If you want to avoid (a), you have to build all sorts of additional structures, and still you need some sort of audit process to *prove* that you have no gaps.

I've chosen not to elaborate on how you'd do this ... because its a bad idea. If you *really* want it (sigh) then add a review and we'll show you