Generators no Firebird 1.5.1
Caros colegas,
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:
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....
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
Curtidas 0
Respostas
Bolus
01/09/2004
Completando a Questão anterior....
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
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
Agradeço qualquer ajuda possivel....
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
Fsflorencio
01/09/2004
É possível no Firebird 1.5.
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.
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
Bolus
01/09/2004
Efetuei alguns teste básicos e parece que vai solucionar o meu problema...
Confirmarei mais tarde a solução apresentada se vai ser possivel colocar em produção...
Agradeço sua ajuda...
Confirmarei mais tarde a solução apresentada se vai ser possivel colocar em produção...
Agradeço sua ajuda...
GOSTEI 0
Bolus
01/09/2004
Caro colega,
efetuei alguns testes mais profundos...
Realmente para Criar os comandos
Funcionou perfeito, porém para a recuperação do generator não funcionou ...
As linhas de código que utilizei foram:
também tentei do seguinte modo:
e
a REsposta que recebi foram:
SQL Code Error: -104
GEN_ID
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
Beppe
01/09/2004
Em vez de chamar gen_id diretamente, use um select:
Declare ID como [b:a502a175c1]bigint[/b:a502a175c1].
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
Bolus
01/09/2004
Beppe,
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....
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
Beppe
01/09/2004
Mas vc continua usado generators no código que eu postei. Você só altera um comando, em vez de usar gen_id como função solita, você a usa dentro de um select. É gen_id que recuperará e atualizará o valor do generator.
Percebe?
Percebe?
GOSTEI 0
Bolus
01/09/2004
Observei sua resposta e apliquei na Trigger da seguinte maneira:
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...
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
Invalid Token.
Dynamic SQL Error
SQL Code Error: -104
Token unknown - line 1, char 35.
0.
Qual seria o caminho neste ponto, estou começando a ficar irritado com o código...
Qualquer ajuda cairia bem, novamente...
GOSTEI 0
Beppe
01/09/2004
Tem um erro sintático na criação da sua trigger. A sintaxe dela deveria ser algo assim:
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
Bolus
01/09/2004
Beppe,
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...
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
Beppe
01/09/2004
bolus, o erro acusado ´Invalid Token...0´, sugere um erro sintático. Como você disse agora que é na execução, o erro deve estar no execute statement, mas não vi o tal 0 que está causando o erro. Veja no sql monitor se a sentença está bem formada.
GOSTEI 0
Afarias
01/09/2004
bom pessoal... no ´final das contas´ temos::
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+
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
Vinicius2k
01/09/2004
Colegas,
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 :
o resultado seria :
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+
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
Bolus
01/09/2004
Caros colegas,
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.
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
Bolus
01/09/2004
Caros colegas,
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:
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...
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
Bolus
01/09/2004
Caros colegas,
Encontrei o erro que esta ANTA fez....
na linha
deveria ser colocado assim:
Estava faltando um espaço ( ASCII(32)) antes da palavra TO...
Agradeço a ajuda de todos os colegas.....
Encontrei o erro que esta ANTA fez....
na linha
sGEN = ´Set Generator GEN_CLIFILIAL´||new.Empresa||´_´|| New.Filial|| ´to 0´;
deveria ser colocado assim:
sGEN = ´Set Generator GEN_CLIFILIAL´||new.Empresa||´_´|| New.Filial|| ´ to 0´;
Estava faltando um espaço ( ASCII(32)) antes da palavra TO...
Agradeço a ajuda de todos os colegas.....
GOSTEI 0