Fórum Generators no Firebird 1.5.1 #46475
01/09/2004
0
Gostaria de efetuar o seguinte procedimento:
- Ao cadastrar um REgistro (Ex.: Filial), criar um Generator ,GEN_CLIFILXX, onde XX seria o código do Cadastro da Filial.
- Quando incluisse um novo cliente na Filial, seria utilizado esse Generator para Gerar o Código do Cliente
- Como seria criado uma Trigger no Insert do Cliente, dependendo da Filial seria um Generator diferente (Ex.: Filial 01 - GEN_CLIFIL01, Filial 02 - GEN_CLIFIL02, etc...)..
Para criar o Generator utilizei o seguinte código:
insert into RDB$GENERATORS(RDB$GENERATOR_NAME, rdb$generator_id) Values(´GEN_CLIFILIAL´||new.Empresa ||´_´|| New.Filial,0);
Porém não consegui utilizar na função gen_id, ou melhor, não conseguo montar uma variável dinamicamente com o nome do generator para utilizar no gen_id
Isso é possivel no Firebird????
Agradeço qualquer ajuda....
Bolus
Curtir tópico
+ 0Posts
01/09/2004
Bolus
a Criação e Utilização do Generator é para ser ativado/utilizado no proprio Servidor, através de Triggers e Stored Procedure, bem como zerar o Generator..
Apesar de no material do Firebird 1.5.1 informar o seguinte comando
set generator XXXX to 9999;
onde XXXX - seria o nome do Generator
9999 - seria o numero a atribui ao generator.
Não consegui utilizar estes comando em uma Stored Procedure, tendo que utilizar o seguinte codigo
iGEN = gen_id(Fatura,0) * -1; /* multiplicação por menos um */ iGEn = gen_id(Fatura,iGEN); /* desta maneira zerei o generator Fatura */
Agradeço qualquer ajuda possivel....
Gostei + 0
02/09/2004
Fsflorencio
Utilize a função EXECUTE STATEMENT
Você pode usar comandos DDL com esta função:
Ex:
Crie uma variável do tipo Varchar(1000) e outra Inteira (ou então use parâmetros da procedure para informar estes valores);
TEXTO VARCHAR(1000);
FILIAL INTEGER;
TEXTO = ´CREATE GENERATOR GEN_CLIFILIAL´ || CAST(FILIAL AS VARCHAR(1) );
EXECUTE STATEMENT TEXTO;
TEXTO = ´SET GENERATOR GEN_CLIFILIAL´ || CAST(FILIAL AS VARCHAR(1) ) || ´ TO 9999´;
EXECUTE STATEMENT TEXTO;
Você também pode obter resultados com a função execute statement:
Ex: retornar o maior código de filial da tabela empresas para criar os generators.
DECLARE VARIABLE RETORNO INTEGER;
texto = ´SELECT MAX(COD_FILIAL) FROM EMPRESAS´
EXECUTE STATEMENT TEXTO INTO :RETORNO;
RETORNO = RETORNO + 1;
TEXTO = ´CREATE GENERATOR GEN_CLIFILIAL´ || CAST(RETORNO AS VARCHAR(1) );//aqui concatena uma variável texto com uma inteira
EXECUTE STATEMENT TEXTO;
Acredito que isto deve resolver seu problema.
Gostei + 0
07/09/2004
Bolus
Confirmarei mais tarde a solução apresentada se vai ser possivel colocar em produção...
Agradeço sua ajuda...
Gostei + 0
07/09/2004
Bolus
efetuei alguns testes mais profundos...
Realmente para Criar os comandos
Create Generators XXXX; e Set Generator XXXX to 0;
Funcionou perfeito, porém para a recuperação do generator não funcionou ...
As linhas de código que utilizei foram:
sGEN = ´Gen_ID(GEN_CLIFILIAL´||new.Empresa||´_´|| New.Filial || ´,1)´; execute statement sGEN into :iGEN;
também tentei do seguinte modo:
sGEN = ´Gen_ID(GEN_CLIFILIAL´||new.Empresa||´_´|| New.Filial || ´,1) into :iGEN´; execute statement sGEN;
e
sGEN = ´iGEN = Gen_ID(GEN_CLIFILIAL´||new.Empresa||´_´|| New.Filial || ´,1)´; execute statement sGEN;
a REsposta que recebi foram:
SQL Code Error: -104
GEN_ID
Gostei + 0
07/09/2004
Beppe
execute statement ´select gen_id(GEN_CLIFILIAL´ || new.Empresa || ´_´ || new.Filial || ´, 1) from rdb$database´ into :ID;
Declare ID como [b:a502a175c1]bigint[/b:a502a175c1].
Gostei + 0
07/09/2004
Bolus
Obrigado por sua resposta, porem gostaria que o trabalho de controle fosse controlado pelas rotinas Internas do Firebird, por isso estou utilizando o Generators.
Por que inicialmente tinha pensado em criar uma tabela que conteria os contadores, assim todos os contadores seriam controlados por minha aplicação, ou melhor por selects, insert e update. Caso não tenha outra solução, voltarei a essa opção inicialmente gerada.
É que existe a possibilidade de ter muitas conexões simultaneas e seria bom que o controle fosse efetuado pelo Gerenciador do Banco de Dados.
Mesmo assim agradeço a ajuda de todos....
Gostei + 0
07/09/2004
Beppe
Percebe?
Gostei + 0
07/09/2004
Bolus
AS declare variable iGen Int; begin /* Trigger text */ if (New.Filial is null) then begin execute statement ´select Cast(gen_id(GEN_FILEMP_´||New.Empresa ||´,1) as Integer) from rdb$database´ INTO :iGEN; new.Filial=iGEN; end end
Porem esta dando a seguinte mensagem de erro
Qual seria o caminho neste ponto, estou começando a ficar irritado com o código...
Qualquer ajuda cairia bem, novamente...
Gostei + 0
07/09/2004
Beppe
CREATE TRIGGER NOME_DA_TRIGGER FOR SUA_TABELA ACTIVE BEFORE INSERT POSITION 0 AS declare variable iGen Int; begin /* Trigger text */ if (New.Filial is null) then begin execute statement ´select Cast(gen_id(GEN_FILEMP_´||New.Empresa ||´,1) as Integer) from rdb$database´ INTO :iGEN; new.Filial=iGEN; end end
Gostei + 0
07/09/2004
Bolus
Somente lhe enviei o corpo da Trigger...
Pois ela não gerou erro ao ser criada, mas sim quando esta sendo acionada pelo Banco....
Ou seja quando estou incluindo um registro no meu arquivo os dados coletados é o erro ocorre...
Alguma sugestão...
Gostei + 0
07/09/2004
Beppe
Gostei + 0
08/09/2004
Afarias
1- ter 1 generator para cada filial nào é uma soluçào ´legal´ (Relacional)
2- EXECUTE STATEMENT é algo q deve ser usado ´em último caso´
qual a ´idéia´ de se ter códigos repetidos para os clientes de filiais diferentes?? isso não é bom em qualquer aspécto.
vc deveria (na minha opnião) ter simplesmente apenas 1 generator criando códigos para TODOS os clientes seja de que filial for e apenas um campo chamado FILIAL para informar a qual filial pertence.
T+
Gostei + 0
08/09/2004
Vinicius2k
Dentro do que o afarias colocou, me permitem sugerir uma coisa ?
1. Manter apenas um generator para cada empresa.
2. Se vc quiser que a ID seja realmente diferente (nestes casos eu prefiro usar uma chave primária concatenada = IDEmpresa e IDCliente), vc pode incrementar o generator baseado num critério, por exemplo, é possível que vc tenha no seu banco 10 milhoes de clientes? se vc achar que é impossível vc poderia dar o valor ao campo ID com um código parecido com este :
New.ID = (IDEmpresa * 10000000) + GEN_ID(Nome_do_Generator, 1);
o resultado seria :
Empresa IDCliente ------------------- 001 0010000001 001 0010000002 001 0010000003 002 0020000004 002 0020000005 003 0030000006 ... ... 214 2149999999
Neste caso vc poderia ter até 214 empresas (para não ter problemas com o tipo integer)... e 9.999.999 clientes (contagem geral de todas elas)...
É apenas uma sugestão...
T+
Gostei + 0
08/09/2004
Bolus
A ideia é criar um sistema MultiEmpresa que conterá diversas Empresas, com uma quantidade variavel de Filiais e consequentemente diversos clientes....
Como o sistema poderá ser acionado por filiais diversas e empresas diferentes, foi planejada esta solução, pois não ocorrerá duplicação do codigo gerado.
O sistema será utilizado, inicialmente, individualmente nas Filiais, por isso não poderei ter um contador unico para a empresa. Depois será colocado em uma central de controle, que deverá continuar com os contadores já inicializados...
Esta solução beneficia um grande numero de clientes, afinal o código gerado vai ser baseado em Codigo da empresa, código da filial e codigo do cliente na filial, ficando com uma numeração semelhante a demonstrada abaixo:
XXX YYY CCCCCC
onde XXX - Codigo da Empresa (até 999)
YYY - Código da Filial na Empresa (até 999 filiais)
CCCCCC - Código do Cliente na Filial ( até 999999)....
Isso abre uma infinidade de códigos, até o suficiente para cadastrar todos os habitantes da terra.
Espero ter dado uma visão, do por que pretendo utilizar um Generator para a empresa, um generator para filial por empresa e um generator para cliente por filial da empresa.....
Ok....
Espero ter esclarecido o motivo dos generators
Qualquer dúvida entrem em contato.
Gostei + 0
09/09/2004
Bolus
Desculpe a informação erronea.....
Após teste na Trigger (Before Insert) informada anteriormente, identifiquei que a mesma esta correta..... O que estava ocasionando erro é a Trigger (After Insert), que coloco Abaixo:
AS declare variable sGEN varchar(256); begin /* Trigger text */ sGEN = ´Create Generator GEN_CLIFILIAL´||new.Empresa||´_´|| New.Filial; Execute statement SGEN; sGEN = ´Set Generator GEN_CLIFILIAL´||new.Empresa||´_´|| New.Filial|| ´to 0´; Execute statement SGEN; end
Não esquecendo que somente coloquei o corpo da Trigger, que por sinal desativei momentaneamente até solucionar o meu erro...
Pois considero que tenha escrevito algum erro na trigger...
Peço a ajuda dos colega...
Novamente peço desculpa pela informação sobre a trigger errada...
Gostei + 0
Clique aqui para fazer login e interagir na Comunidade :)