.comment-link {margin-left:.6em;}

Friday, January 20, 2006

Evitando GAPS em sistemas

Alguns sistemas não têm jeito! Necessitam de número seqüencial para alguns de seus campos. Seja nota fiscal, pedidos, enfim, são vários os exemplos. Para este tipo de sistema o analista NÃO DEVE CONSIDERAR sequence do Oracle. Veja que mesmo o manual aconselha isso:


Caution: If your application can never lose sequence numbers, then you cannot use Oracle sequences, and you may choose to store sequence numbers in database tables. Be careful when implementing sequence generators using database tables. Even in a single instance configuration, for a high rate of sequence values generation, a performance overhead is associated with the cost of locking the row that stores the sequence value.


Fato!

Precisamos de números livres de gaps.

Como fazer?

O que é preciso considerar e lidar, é a serialização no momento de ¨pegar¨ um número, o sistema colocará um semáforo (lock) e permitirá somente um acesso de cada vez.

Pense na serialização como algo parecido com banheiro de posto de gasolina, onde a chave fica no caixa, ou seja, vai um de cada vez. Se sua aplicação é aquele posto pouco freqüentado, tudo bem, quase nunca haverá fila; agora se seu posto for aquele do momento (bombando mesmo) - imagine o desconforto de enfrentar uma fila! Por isso o desenho da aplicação deve considerar performance.

Então como você faria?

Criaria uma tabela IOT com a descrição do ID necessário e manteria ali o último registro. Concluindo com uma função, onde buscaria o descrição do id e devolveria o número seqüencial livre de gaps. Ainda que ocorra GAP é possível "ajustar" essa tabela facilmente.

SQL> create table
2 ids (
3 name varchar2(30) constraint ids_pk primary key,
4 id number
5 ) organization index
6 ;

Table created.

SQL>
SQL> create or replace
2 function get_nextval( p_name in varchar2 ) return number
3 is
4 l_id number;
5 begin
6 update ids set id = id+1
7 where name = upper(p_name)
8 returning id into l_id;
9
10 if ( sql%rowcount = 0 )
11 then
12 raise_application_error( -20001,
13 'Nao existe id para ' || p_name);
14 end if;
15 return l_id;
16 end;
17 /

Function created.

SQL>
SQL> var n number
SQL> exec :n := get_nextval('NF')
BEGIN :n := get_nextval('NF'); END;

*
ERROR at line 1:
ORA-20001: Nao existe id para NF
ORA-06512: at "OPS$MARCIO.GET_NEXTVAL", line 11
ORA-06512: at line 1



N
-------------


SQL> insert into ids values ('NF', 0 );

1 row created.

SQL> exec :n := get_nextval('NF')

PL/SQL procedure successfully completed.


N
-------------
1

Labels:


Comments:
Marcio, agora é só tomar cuidado com o trovões :o)
 
Post a Comment



<< Home

This page is powered by Blogger. Isn't yours?