[firebase-br] Aos interessados: Omelhor Autoincrementosequencial
Caio Oliveira
news em caiosistemas.com.br
Qui Abr 6 12:22:58 -03 2006
Vou expor uma outra técnica semelhante ao uso da função MAX; nunca tive
problemas com numeração de documentas e possuo instalações com mais de
160 usuários concorrentes. Não é a solução mais rápida; mas não falha nunca.
Uma Procedure que lê o último código utilizado (no meu caso a base foi
convertida de um sistema antigo feito em Clipper e usava campos caracter
para o código; mantivemos após conversão; portanto se vc usa campos
INTEGER basta esquecer os processos de conversão utilizados abaixo).
/*
PEDIDOS DE VENDA / NOTAS FISCAIS
GETULTIMOPEDIDONOTA
Devolve o numero do ultimo PEDIDO DE VENDA ou NOTA FISCAL em CEPNT001
*/
^
CREATE PROCEDURE "GETULTIMOPEDIDONOTA"
(
"IDEMP" INTEGER,
"SERIE" CHAR(3)
)
RETURNS
(
"NUMERO" INTEGER
)
AS
DECLARE VARIABLE "ROWS" INTEGER;
Begin
ROWS = 0;
FOR select CAST(NF_NOTA AS INTEGER)+1 from CEPNT001
where id_emp = :idemp AND NF_SERIE = :serie order by NF_NOTA DESC
into :NUMERO
DO
SUSPEND;
Begin
if (NUMERO is null) then NUMERO = 1;
rows = rows + 1;
if (rows = 1) then EXIT;
End
END
^
Uma TRIGGER que é aciona a procedure e incrementa o campo código; alêm
do ID do registro e data
/*
TG_PEDIDOSNOTAS
-------------------------
Essa TRIGGER insere o numero do próximo doc. Documento (NOTA FISCAL)
ou PEDIDO DE VENDA na tabela CEPNT001 e ainda o ID do documento e data.
Autor: Caio José Hugueney Lopes de Oliveira
*/
^
CREATE TRIGGER TG_PEDIDOSNOTAS FOR CEPNT001
ACTIVE BEFORE INSERT
POSITION 0
AS
DECLARE VARIABLE PROXNUM INTEGER;
DECLARE VARIABLE PROXCOD VARCHAR(6);
BEGIN
EXECUTE PROCEDURE GETULTIMOPEDIDONOTA( NEW.ID_EMP, NEW.NF_SERIE )
RETURNING_VALUES PROXNUM;
IF (PROXNUM IS NULL) THEN PROXNUM = 1;
EXECUTE PROCEDURE PC_STRZERO PROXNUM, 6
RETURNING_VALUES PROXCOD;
IF (NEW.ID_CEPNT001 IS NULL) THEN
NEW.ID_CEPNT001 = GEN_ID( GEN_CEPNT001, 1);
NEW.DATAHORA = CURRENT_TIMESTAMP;
IF (NEW.NF_DATA IS NULL) then NEW.NF_DATA = CURRENT_DATE;
IF ((NEW.NF_NOTA IS NULL) OR (NEW.NF_NOTA='')) then
NEW.NF_NOTA = PROXCOD;
END;
^
Essa procedure PC_STRZERO é chamada apenas para converter e CHAR e
incrementar com zeros à esquerda o número obtido; quem se interessar
segue o código abaixo:
/* PC_StrZero(str)
// Essa procedure devolve o tamanho da STRING passada como parâmetro.
// Original de: Ivan Prenosil
Adaptada por Caio Jose Hugueney Lopes de Oliveira */
CREATE PROCEDURE PC_StrZero (vstr VARCHAR(100), nTam INT)
RETURNS (vstr2 varchar(100)) AS
DECLARE VARIABLE vallen INT;
BEGIN
vstr2 = null;
EXECUTE PROCEDURE PC_LEN vstr
RETURNING_VALUES vallen;
IF (vstr IS NULL) THEN EXIT;
IF (nTam IS NULL) THEN EXIT;
vstr2 = vstr;
WHILE (nTam > vallen) DO
BEGIN
vstr2 = '0'||vstr2;
vallen = vallen +1;
END
END
^
/* PC_len(str)
// Essa procedure devolve o tamanho da STRING passada como parâmetro.
// Original de Ivan Prenosil
Adaptada por: Caio José Hugueney Lopes de Oliveira */
CREATE PROCEDURE PC_Len (str VARCHAR(100))
RETURNS (len INTEGER) AS
DECLARE VARIABLE pat VARCHAR(100);
BEGIN
len = null;
IF (str IS NULL) THEN EXIT;
pat = '';
len = 0;
WHILE (NOT str LIKE pat) DO BEGIN
pat = pat || '_';
len = len + 1;
END
END
^
Abraço à todos!
Caio
Eduardo Jedliczka (TeamFB) escreveu:
> Bom, deixa eu por lenha da fogueira...
>
> NÃO EXISTE SOLUÇÃO MÁGICA PARA NÚMEROS ININTERRUPTOS SEQUENCIAIS EM BANCO DE
> DADOS RELACIONAIS.
>
> Se você precisa se preocupar em "Sequencias Reais" em Notas Fiscais,
> Cheques, e outros documentos deste porte, não adianda usar um
> Sequence/Generator (nem no Oracle!!!), e tem que se ter muito sangue frio
> para se utilizar "Select Max" em aplicações com mais que meia-dúzia de
> operadores simultâneos.
>
> Há paliativos "universais" para se resolver isto, entre eles uma "tabela de
> gabarito" contendo (dependendo do caso) os "furos" e códigos ainda não
> utilizados na emissão de documentos. Só vale lembrar, que para isto
> funcionar, é necessário que esta tabela esteja numa transação "diferente"
> (auto-commit, read-commited, with lock), onde só será consultada e alterada,
> após o Commit da transação principal.
>
> Também há soluções "exclusivas" do InterBase/FireBird... pode-se utilizar
> "eventos" para capturar qual foi o último número de nota/cheque emitido e
> assim criar uma sequencia sem falhas.
>
> (Cantu que tal acrescentar este assunto na temática das palestras do 3º FDD
> ???)
>
> ======================
> Eduardo Jedliczka
> Membro do TeamFB - FireBase
> Apucarana - PR
> ======================
>
> ----- Original Message -----
> From: "Andrei Luís" <compuvale.software em gmail.com>
> To: "FireBase" <lista em firebase.com.br>
> Sent: Thursday, April 06, 2006 9:17 AM
> Subject: Re: [firebase-br] Aos interessados: Omelhor
> Autoincrementosequencial
>
>
> Uma solução que se usava bastante na época do Clipper, era de uma tabela a
> parte para guardar a sequência. Ex.:
>
> Tabela Campo Sequencia
> Clientes ID 1
> Produtos ID 4
> Pedidos ID 10
> ...
>
> Acho que saiu na Clube Delphi ou na SQL Magazine uns meses atras uma solução
> parecida com essa, o título era algo como: "Campos auto-incremento para
> qualquer BD". O colunista usou Firebird para mostrar os exemplos.
>
> []
> Andrei
>
>
> Em 06/04/06, Luis Asensio - Control/P Sistemas <luis em controlp.com.br>
> escreveu:
>> Boa dia a todos!!!
>>
>> Essa semana fiz um teste comparando a eficiencia do auto-incremento
>> das duas formas descritas. Uma realizando um MAX na tabela e outra usando
>> a
>> Generator. O teste foi bem simples: Rodei uma aplicatico no qual me inflou
>> uma determinada tabela em 100.000 e inserir um cronometro interno para
>> poder
>> comparar o tempo. O resultado foi uma diferença de 3:00 min, a mais para o
>> Trigger com o MAX. O Generator com muitos registros é mais rápido acima de
>> 20.000 registros. Concordo que para um sequencial integro o MAX minimiza o
>> problema.
>>
>>
>> Abraços
>>
>>
>> Luis Asensio
>> Control/P Sistemas
>> Setor de Desenvolvimento
>> luis em controlp.com.br
>> http://www.controlp.com.br
>>
>> -----Original Message-----
>> From: lista-bounces em firebase.com.br [mailto:lista-bounces em firebase.com.br]
>> On Behalf Of Listas - VirtualComp
>> Sent: quarta-feira, 5 de abril de 2006 18:12
>> To: Carlos H. Cantu; FireBase
>> Subject: Re: [firebase-br] Aos interessados: Omelhor
>> Autoincrementosequencial
>>
>> CREATE TRIGGER GER_COD_CLIENTES FOR CLIENTES ACTIVE BEFORE INSERT POSITION
>> 0
>> AS declare variable cod integer; begin select max(codigo_cli) from
>> clientes where clientes.empresa_cli = new.empresa_cli into :cod; if
>> (cod
>> is null) then
>> cod = 0;
>> new.codigo_cli = cod + 1;
>> end
>>
>>
>> com essa trigger eu tenho 3..4 empresas cadastradas cada empresa tem uma
>> sequencia clientes e nunca da problema...
>>
>>
> ______________________________________________
> FireBase-BR (www.firebase.com.br) - Hospedado em www.bavs.com.br
> Para editar sua configuração na lista, use o endereço
> http://mail.firebase.com.br/mailman/listinfo/lista_firebase.com.br
> Para consultar mensagens antigas: http://firebase.com.br/pesquisa
>
>
> ______________________________________________
> FireBase-BR (www.firebase.com.br) - Hospedado em www.bavs.com.br
> Para editar sua configuração na lista, use o endereço http://mail.firebase.com.br/mailman/listinfo/lista_firebase.com.br
> Para consultar mensagens antigas: http://firebase.com.br/pesquisa
>
Mais detalhes sobre a lista de discussão lista