Sequence using merge or other alternative

Hello

I have the following table, wherein a SUBS_ID is unique but INDEX_ID is not and REQUEST_ID is initially null for all records.

The table can be large (~ 1 M lines) and even though there might be several SUBS_ID with INDEX_ID even - most of the records have 1 to 1 relationship.

CREATE GLOBAL TEMPORARY TABLE SUBS_HIERARCHY_TEMP
(
  SUBS_ID     NUMBER(10)                        NOT NULL,
  INDEX_ID   NUMBER(10)                         NOT NULL,
  REQUEST_ID  NUMBER(10)
)
ON COMMIT DELETE ROWS;

I have the code which assigns a unique number (REQUEST_ID) to each separate INDEX_ID using a sequence (this code can run in parallel and I REQUEST_ID must be unique in the world):

...
        cursor Request_id_cur is
        select distinct INDEX_ID
        from SUBS_HIERARCHY_TEMP;
...
begin
...
   -- fill SUBS_HIERARCHY_TEMP with records, doesn't matter how, REQUEST_ID remains NULL
   -- populate REQUEST_ID with a sequence

     for SUB in Request_id_cur LOOP
         v_UniqeIndex := SEQ_REQUEST_ID.nextval;


         Update SUBS_HIERARCHY_TEMP
         set REQUEST_ID = v_UniqeIndex
         where INDEX_ID = SUB.INDEX_ID;
    END LOOP;
...
end;

It works - but obviously not very efficient. If all the records are 1-1 going to run updates of 1 M, but I can't use a simple update in case somewhere SUBS_ID INDEX_ID even therefore need to have the same REQUEST_ID.

I tried to do it in one go using a merge statement, but apparently the sequences are not allowed in the USING clause of the merger:

merge into SUBS_HIERARCHY_TEMP tab
using (select INDEX_ID, SEQ_REQUEST_ID.nextval as REQUEST_ID
       from (select distinct INDEX_ID
             from SUBS_HIERARCHY_TEMP)
      )tmp
on (tab.INDEX_ID=tmp.INDEX_ID)
when matched then update
    set REQUEST_ID=tmp.REQUEST_ID;

ORA-02287: sequence number not allowed here

Any ideas how to make in a single statement and avoid the loop?

I'm on 11.2.0.3 RHEL6 64bits.

Thanks in advance.

drop table SUBS_HIERARCHY_TEMP purge;

CREATE GLOBAL TEMPORARY TABLE SUBS_HIERARCHY_TEMP (
  SUBS_ID     NUMBER(10)                        NOT NULL,
  INDEX_ID   NUMBER(10)                         NOT NULL,
  REQUEST_ID  NUMBER(10)
)
ON COMMIT DELETE ROWS;

drop sequence seq;
create sequence seq;

drop type tt_subs_rec
/
create or replace type t_subs_rec as object(
  SUBS_ID     NUMBER(10),
  INDEX_ID   NUMBER(10),
  REQUEST_ID  NUMBER(10)
)
/
create type tt_subs_rec as table of t_subs_rec
/
create or replace function sub_hierarchy_update return tt_subs_rec pipelined
as
  l_subs_rec t_subs_rec := t_subs_rec(null,null,null);
  prev_INDEX_ID SUBS_HIERARCHY_TEMP.INDEX_ID%type := -9999999;
  l_request_id SUBS_HIERARCHY_TEMP.REQUEST_ID%type;
begin
  for rec in (
    select subs_id, index_id, request_id
    from SUBS_HIERARCHY_TEMP
    order by index_id
  ) loop
    if prev_INDEX_ID < rec.index_id then
      prev_INDEX_ID := rec.index_id;
      l_request_id := seq.nextval;
    end if;
    l_subs_rec.subs_id := rec.subs_id;
    l_subs_rec.INDEX_ID := rec.INDEX_ID;
    l_subs_rec.request_id := l_request_id;
    pipe row(l_subs_rec);
  end loop;
  return;
end sub_hierarchy_update;
/

insert into SUBS_HIERARCHY_TEMP
select level, mod(level-1,3)+1, null
from dual
connect by level <= 9;

select * from subs_hierarchy_temp;
SUBS_ID INDEX_ID REQUEST_ID
1 1
2 2
3 3
4 1
5 2
6 3
7 1
8 2
9 3
select * from table(sub_hierarchy_update);
SUBS_ID INDEX_ID REQUEST_ID
4 1 1
1 1 1
7 1 1
2 2 2
5 2 2
8 2 2
3 3 3
6 3 3
9 3 3

Tags: Database

Similar Questions

Maybe you are looking for