Auto numeração via Código.

Firebird

11/12/2003

Tenho um campo código na tabela e quero inseri-lo via edit, mas sempre acrescentando+1. Sei que existe o generator(nunca usei), mas existe alguma maneira de implementa-lo(acrescentando+1) via código?
Se faço via beforPost acrescenta+2, no botão Npost do navigator então acusa a mensagem que o campo está vazio, enfim, é isso.
Quero jogar esse número do código depois do preenchimento do cadastro, estou pensando no uso em uma rede.


Amilton/pr

Amilton/pr

Curtidas 0

Respostas

Afarias

Afarias

11/12/2003

crie um generator no banco::

CREATE GENERATOR nome_generator;


crie a seginte ´função´ no delphi::


function TFormx.GetNewID(const AGenerator: string): Integer;
const
  SQLText = ´select gen_id(¬s, 1) from rdb$database´;
begin
  with IBSQL1 do
  begin
    SQL.Text := Format(SQLText, [AGenerator]);
    Transaction.StartTransaction;
    try
      ExecQuery;
      Result := Fields[0].AsInteger;
    finally
      Transaction.Commit;
    end;
  end;
end;




vc pode substituir o IBSQL por outro componente q esteja usando (que execute SQLs no IB)

vc pode usar o seginte código para pegar um novo código (no BeforePost ou OnNewRecord do seu DataSet)::

  SeuDataSet.FieldByName(´CODIGO´).AsInteger := GetNewID(´nome_generator´);


se tiver problemas com ´campo está vazio´ ... defina a propriedade REQUIRED do TField que representa o campo Código para FALSE.


T+


GOSTEI 0
Amilton/pr

Amilton/pr

11/12/2003

Blz., mas posso usar esse código no Botão nPost do Navigator ou tenho que colocar um botão pra gravar?


GOSTEI 0
Afarias

Afarias

11/12/2003

Vc pode colocar onde quizer! Mas, é bom colocar as coisas no seu devido lugar ... sendo assim, aconselho q coloque o código nos eventos BeforePost ou OnNewRecord do DataSet.

Mas, como disse, vc pode colocar onde quizer.


T+


PS:: No caso de colocar no BeforePost, vc teria q antes ´perguntar´

if DataSet.State = dsInsert then
{...}


GOSTEI 0
Amilton/pr

Amilton/pr

11/12/2003

Nessa Gerator . . .

1-function TFormx.GetNewID(const AGenerator: string): Integer;
2-const
3- SQLText = ´select gen_id(¬s, 1) from rdb$database´;
4-begin
5- with IBSQL1 do
6- begin
7- SQL.Text := Format(SQLText, [AGenerator]);
8- Transaction.StartTransaction;
9- try
10- ExecQuery;
11- Result := Fields[0].AsInteger;
12- finally
13- Transaction.Commit;
14- end;
15- end;
16-end;

Fiz uma numeração de linhas pra mostrar que dá erro na linha 7(acho que o ponto, mas tirei esse ponto e mesmo assim dá erro) e depois na linha 10.


GOSTEI 0
Afarias

Afarias

11/12/2003

Bom, não sei se já te falei: procure manter cada dicussão no seu lugar ok? Especificamente esta, vamos manter e continuar apenas aqui certo??


Bom, não há erros neste procedimento, então::

Qual a mensagem de erro q vc está recebendo??



T+


GOSTEI 0
Amilton/pr

Amilton/pr

11/12/2003

Muito bem, meu amigo!!!!
Olha, criei um Generator com o nome de P_Gener, com o valor 0.
Na função na linha:
SQLText := Format(SQLText, [AGenerator]);

Obs. na instrução está sql.text, aqui é sqltext, sem o ponto. Com o ponto dá a mensagem : undeclared Identifier SQL.

mensagem de erro nessa instrução: left side cannot be assigned to

Aguaro retorno . . .


GOSTEI 0
Amilton/pr

Amilton/pr

11/12/2003

Ainda sobre o Generator na linha ExecQuery;

Essa mensagem: Undeclared Identifier ´ExecQuery´

Para complementar sobre o Generator em questão . . .


GOSTEI 0
Afarias

Afarias

11/12/2003

|criei um Generator com o nome de P_Gener, com o valor 0.
|Na função na linha: SQLText := Format(SQLText, [AGenerator]);

NÃO É SQLText := {...} é ::: SQL.Text := {...}

TEM o PONTO ok?! SQL é uma propriedade do IBSQL que é do tipo TStrings. E Text é uma propriedade do TStrings.

Depois no Format, tem SQLText (sem ponto) que, se vc reparar é o nome da constante criada!! (Vc pode renomear a constante para outro nome q mais lhe agradar)

Vc usaria a função da forma (EX.)::

MinhaVariavel := GetNewID(´P_GENER´);


|Obs. na instrução está sql.text, aqui é sqltext, sem o ponto. Com o ponto
|dá a mensagem : undeclared Identifier SQL.

É pq vc provavelmente não está usando um IBSQL. Se vc está usando outro componente, tem q mudar algumas coisas no código para este componente específico.


|Ainda sobre o Generator na linha ExecQuery;
|Essa mensagem: Undeclared Identifier ´ExecQuery´

Mesma coisa!


T+


GOSTEI 0
Amilton/pr

Amilton/pr

11/12/2003

Legal!
Realmente . . . estou usando o componente IbDataset e ele não tem a propriedade SQL, mas substitui pelo comando SelectSql.text e não deu o erro mais. Agora na linha ExecQuery continua com a mesma situação.
Tem algum comando para executar um IbDataset como um IbQuery pra resolvermos isso?


GOSTEI 0
Afarias

Afarias

11/12/2003

Já q vc está usando IBX, não é mais fácil vc simplesmente usar um IBSQL no lugar do IBDataSet?? Cada coisa no seu lugar -- o IBDataSet não é feito pra isso, o IBSQL sim.


T+


GOSTEI 0
Amilton/pr

Amilton/pr

11/12/2003

Posso perfeitamente fazer isso, na verdade eu não sei exatamente como funciona e nem as diferenças entre ambos, mas no caso da IbQuery como fica alterar, incluir, deletar, enfim . . . a manutenção em geral se não tem as propriedades InsertSql, DeleteSql, etc?

Poderia me dizer as diferenças e funções desses componentes?


GOSTEI 0
Afarias

Afarias

11/12/2003

Veja Amilton,

Para selecionar os registros e editá-los, vc deve usar um IBDataSet Ok??

Se vc quer gerar o código automático direto no IBDataSet, vc pode usar a propriedade GeneratorField para isso Ok??

Bom, como vc quer gerar o valor via código... vc deve usar uma função como aquela -- é algo a parte -- não tem nada a ver com a seleção e edição de registros!!!! É só pra gerar um novo código em qualquer parte q vc desejar certo???

E eu não disse IBQuery eu disse IBSQL, os componentes IBX são divididos mais ou menos assim::


IBTable - não serve pra nada
IBStoredProc - procedimentos ´executáveis´ (os ´selecionáveis´ não)
IBQuery - seleção de registros (e alteração caso usado em conjunto com um IBUpdateSQL)
IBDataSet - é igual a 1 IBQuery + 1 IBUpdateSQL
IBSQL - executar comandos SQL (inclusive consultas -- unidirecional e sem suporte a controles visuais)


T+


GOSTEI 0
Amilton/pr

Amilton/pr

11/12/2003

Desculpe, disse IbQuery mas colei o componente IbSql.
Olha, usei a propriedade GeneratorField para incrmentar o código em 1, no Dataset, assim: Nome da Generetor: P_Gener - Obs. Mudei o valor da Generator para 0;
Field: Codigo
Increment: 1
Apply event: opcao New Record -

Quando rodo o programa dá violação de chave.


GOSTEI 0
Afarias

Afarias

11/12/2003

vc não pode voltar o valor de um generator q está sendo usado se já existem registros na tabela a qual ele se presta. o q vc vai ter é violações de chave primária.


T+


GOSTEI 0
Amilton/pr

Amilton/pr

11/12/2003

Blz. Limpei a tabela e comecei a inserir os dados.
Coloquei o valor da Generator em 0 ou 1, isso incluencia em algo?
Na propriedade GeneratorField na opção ApplyField marquei OnPost e LEGAL!!! agora está funcionando Blz.
Depois de tudo, aparente simples, né?
Pelo que entendi esse código gerado é autoincremento, só conseguirei a editar registros do inicio se limpar a tabela e começar tudo novamente?

Em que situação, então eu usaria o Generator com IbSql?


GOSTEI 0
Afarias

Afarias

11/12/2003

|Coloquei o valor da Generator em 0 ou 1, isso incluencia em algo?

Não


|Depois de tudo, aparente simples, né?

é! :D


|Pelo que entendi esse código gerado é autoincremento, só conseguirei a
|editar registros do inicio se limpar a tabela e começar tudo novamente?

é... vc não pode ficar voltando os valores. não se preocupe com isso, a única função de um código é ser ÚNICO e não ser sequencial (sem buracos).


|Em que situação, então eu usaria o Generator com IbSql?

Várias... quando não se deseja usar a propriedade GeneratorField por algum motivo particular, quando vc não usa IBX (não seria então com IBSQL mas com outro componente com a mesma função), quando se usa MIDAS, etc... (quem manda é o cliente! ;))


T+


GOSTEI 0
Marshall Mathers

Marshall Mathers

11/12/2003

afarias, e se meu campo for chave primária?!??! naum dá pra definir chave primária sem ser not null.... como eu faço entaum?


GOSTEI 0
Afarias

Afarias

11/12/2003

é, chave primária não pode ter NULOS, mas não entendi o q vc quer.

Exclareça melhor sua dúvida.


T+


GOSTEI 0
Amilton/pr

Amilton/pr

11/12/2003

Cara, isso é muito bom. Ficou legal.
Em tabelas Firebird quando se cria um segundo índice(seria um indice secundário, como no Paradox?), como se faz para mudar o indice e usa-lo?, ou via SQL usa-se indice por Order by?

Um abraço!


GOSTEI 0
Amilton/pr

Amilton/pr

11/12/2003

Essa rotina de incremento funciona bem em rede?


GOSTEI 0
Marshall Mathers

Marshall Mathers

11/12/2003

é, chave primária não pode ter NULOS, mas não entendi o q vc quer. Exclareça melhor sua dúvida. T+


Pq o registro naum vai salvar se o edit estiver em branco. Ele vai dar erro na chave primária que não pode ser nula, sakou?


GOSTEI 0
Marshall Mathers

Marshall Mathers

11/12/2003

Uma pergunta rápida.... eu tenho um campo que criei com um DOMAIN para ser booleano, e ae estou usando ele no delphi com CheckBoxes, mas só que na hora em que eu vou salvar um registro em que eu num marquei o checkbox ele dá a seguinte msg:

1ª) Project SysInvent.exe raised exception class EIBInterbaseError with message ´validation error for column CxSom, value ´***null***´. Process stoped, bla,bla,bla......

2ª) validation error for column CxSom, value ´***null***´.

Eu usei o seguinte código para fazer o DOMAIN:

CREATE DOMAIN DM_LOGICO2 AS
CHAR(1) CHARACTER SET WIN1252
DEFAULT ´N´
CHECK ((VALUE IN (´S´,´N´)))
COLLATE PXW_INTL850


E ae, vc pode me ajudar a resolver... só falta isso....

De qualquer forma valeus.....


GOSTEI 0
Marshall Mathers

Marshall Mathers

11/12/2003

Alguém pod me ajudar ae????


GOSTEI 0
Afarias

Afarias

11/12/2003

Vamos por partes....


Amilton/Pr::

|Essa rotina de incremento funciona bem em rede?

Que rotina? A que te passei?? SIM!


|Em tabelas Firebird quando se cria um segundo índice(seria um indice
|secundário, como no Paradox?), como se faz para mudar o indice e usa-
|lo?, ou via SQL usa-se indice por Order by?

Vc apebas cria os índices quem usa é o servidor. Não se preocupe com eles.


Marshall Mathers::

|Pq o registro naum vai salvar se o edit estiver em branco. Ele vai dar
|erro na chave primária que não pode ser nula, sakou?

Coloque o TField em questão como Required=False


|eu tenho um campo que criei com um DOMAIN para ser booleano, e ae
|estou usando ele no delphi com CheckBoxes, mas só que na hora em
| {...}

seu domain não permite NULOS, sendo assim, faça com q seu código sempre jogue apenas ´S´ ou ´N´ no campo



T+


GOSTEI 0
Amilton/pr

Amilton/pr

11/12/2003

Preciso criar um Generator para cada tabela que queiro fazer um autoincremento ou posso usar o mesmo Generator para todas tabelas?


GOSTEI 0
Marshall Mathers

Marshall Mathers

11/12/2003

|seu domain não permite NULOS, sendo assim, faça com q seu código |sempre jogue apenas ´S´ ou ´N´ no campo T+


[color=blue:3f1d612144]Se não for pedir muito, vc pode me dar um exemplo de um DOMAIN assim???[/color:3f1d612144]


GOSTEI 0
Afarias

Afarias

11/12/2003

|Preciso criar um Generator para cada tabela que queiro fazer um
|autoincremento ou posso usar o mesmo Generator para todas tabelas?

Um pra cada CAMPO q receberá os valores (auto-numeração)


|Se não for pedir muito, vc pode me dar um exemplo de um DOMAIN
|assim???

Não entendi... o DOMAIN está correto, vc tem apenas q no código, sempre inserir um dos valores permitidos no domais, nunca inserir Nulos por exemplo. É isso?!


T+


GOSTEI 0
Marshall Mathers

Marshall Mathers

11/12/2003

Não entendi... [b:70e31086c1]o DOMAIN está correto, vc tem apenas q no código, sempre inserir um dos valores permitidos no domais, nunca inserir Nulos[/b:70e31086c1] por exemplo. É isso?!


Certo, mas eu não estou inserindo nulos.... eu fiz o meu campo no FB com esse código de DOMAIN, e ae quando chegou no Delphi eu coloquei CheckBoxes para representar esses campos, e nas propriedades ValueChecked eu coloquei = S e ValueUnchecked=N.... como está no DOMAIN, mas sempre que eu deixo um CheckBox desmarcado ele dá a mesma mensagem.... agora eu num tow intendendo nada..... por favor me ajude....


GOSTEI 0
Afarias

Afarias

11/12/2003

Pq, quando o registro é ´criado´ inicialmente seu valor é NULL e no checkbox aparece desmarcado (se vc não usa aquela opção ´intermediária´) -- para resolver seu problema, apenas faça o seguinte, no evento OnNewRecord da Query/DataSet adicione::

DataSet.FieldByName(´CampoLigadoAoCheckBox´).AsString := ´N´;



T+


GOSTEI 0
Marshall Mathers

Marshall Mathers

11/12/2003

afarias, vc é o cara.... fucionou blz... ufa, posso até respirar melhor, pq meu chefe tava me argolando por causa desse prog e só faltava isso... vc salvou a minha pele... diz ae o q vc ker de natal... eu dou um toque pro bom velhinho te mandar ae.... heheheheh.... [color=red:9d787cf4f5][b:9d787cf4f5]MUITO OBRIGADO MESMO![/b:9d787cf4f5][/color:9d787cf4f5] :D :D :D :D :lol: :lol: :lol: :lol:


GOSTEI 0
POSTAR