Numeração sequecial. Não chave primária.

Delphi

21/12/2007

Galera tenho essa tabela
CREATE GENERATOR ID_LANCAMENTO_PROJETO;

CREATE TABLE LANCAMENTO_PROJETO (
    ID_LANCAMENTO_PROJETO   INTEGER NOT NULL,
    COD_PROJETO_LANCAMENTO  VARCHAR(6),
    COD_ORDENADO_M          VARCHAR(20) NOT NULL,
    COD_GRUPO_FK            INTEGER NOT NULL,
    ITEM                    INTEGER,
    QUANTIDADE_M            VARCHAR(20),
    TOTAL                   NUMERIC(15,2)
);

Tô querendo que o campo ´ITEM´ seja sequencial. Para cada ´COD_PROJETO_LANCAMENTO´ tenha uma sequência separada.
Como faço isso?
[/code]


Jpauloss

Jpauloss

Curtidas 0

Respostas

Delphijean

Delphijean

21/12/2007

Caro jpauloss,
Acho que basta vc crirar um generator, como si vem estivesse usando numa primary key mesmo que nao seja.

espero ter ajudado, se não detalhe melhor suma necessidade.


GOSTEI 0
Micheus

Micheus

21/12/2007

Tô querendo que o campo ´ITEM´ seja sequencial. Para cada ´COD_PROJETO_LANCAMENTO´ tenha uma sequência separada. Como faço isso?

Vc faz uma consulta na sua tabela LANCAMENTO_PROJETO, filtrando o código ID_LANCAMENTO_PROJETO e pegando o MAX do ITEM somado a 1:

select MAX(ITEM) AS ITEM
from LANCAMENTO_PROJETO
where ID_LANCAMENTO_PROJETO = :ID_LANCAMENTO_PROJETO

- passa como parâmetro o ID do projeto e abre a consulta;
- pega o resulta e soma 1 e atribui ao no ITEM desde projeto.

está aí o sequêncial por projeto.


GOSTEI 0
Jpauloss

Jpauloss

21/12/2007

[quote:ccbc835a27=´jpauloss´]Tô querendo que o campo ´ITEM´ seja sequencial. Para cada ´COD_PROJETO_LANCAMENTO´ tenha uma sequência separada. Como faço isso?

Vc faz uma consulta na sua tabela LANCAMENTO_PROJETO, filtrando o código ID_LANCAMENTO_PROJETO e pegando o MAX do ITEM somado a 1:

select MAX(ITEM) AS ITEM
from LANCAMENTO_PROJETO
where ID_LANCAMENTO_PROJETO = :ID_LANCAMENTO_PROJETO

- passa como parâmetro o ID do projeto e abre a consulta;
- pega o resulta e soma 1 e atribui ao no ITEM desde projeto.

está aí o sequêncial por projeto.[/quote:ccbc835a27]
e o valor +1 fica como na prática pode me dar um exemplo com base nesse mesmo que vc colocou?


GOSTEI 0
Micheus

Micheus

21/12/2007

select MAX(ITEM) AS ITEM from LANCAMENTO_PROJETO where ID_LANCAMENTO_PROJETO = :ID_LANCAMENTO_PROJETO

em termos de programação Delphi:
...
Query1.SQL.Clear;
Query1.SQL.Add(´select MAX(ITEM) AS ITEM´);
Query1.SQL.Add(´from LANCAMENTO_PROJETO´);
Query1.SQL.Add(´where ID_LANCAMENTO_PROJETO = :ID_LANCAMENTO_PROJETO´);
Query1.ParamByName(´ID_LANCAMENTO_PROJETO´).AsInteger := <valor do  campo>;
Query1.Open;
Novo_ID_ITEM := Query1.FieldByName(´ITEM´).AsInteger +1;
Query1.Close;
...


Este procedimento deve ser realizado no evento BeforePost do dataset para tentar deixar para o último momento a obtenção deste código.

Espero ter melhorado a explicação.


GOSTEI 0
Jpauloss

Jpauloss

21/12/2007

[quote:744ff9bc1b]select MAX(ITEM) AS ITEM from LANCAMENTO_PROJETO where ID_LANCAMENTO_PROJETO = :ID_LANCAMENTO_PROJETO

em termos de programação Delphi:
...
Query1.SQL.Clear;
Query1.SQL.Add(´select MAX(ITEM) AS ITEM´);
Query1.SQL.Add(´from LANCAMENTO_PROJETO´);
Query1.SQL.Add(´where ID_LANCAMENTO_PROJETO = :ID_LANCAMENTO_PROJETO´);
Query1.ParamByName(´ID_LANCAMENTO_PROJETO´).AsInteger := <valor do  campo>;
Query1.Open;
Novo_ID_ITEM := Query1.FieldByName(´ITEM´).AsInteger +1;
Query1.Close;
...


Este procedimento deve ser realizado no evento BeforePost do dataset para tentar deixar para o último momento a obtenção deste código.

Espero ter melhorado a explicação.[/quote:744ff9bc1b]
NOVO_ID_ITEM é o que?


GOSTEI 0
Micheus

Micheus

21/12/2007

Foi só um nome que usei para ilustrar como vc obteria o próximo código do item utilizando a query como eu havia exemplificado.

Voce pode considerá-la uma variável do tipo Integer, mas também pode ser o campo do seu dataset para o qual vc quer gravar o novo código gerado.


GOSTEI 0
Jpauloss

Jpauloss

21/12/2007

Foi só um nome que usei para ilustrar como vc obteria o próximo código do item utilizando a query como eu havia exemplificado. Voce pode considerá-la uma variável do tipo Integer, mas também pode ser o campo do seu dataset para o qual vc quer gravar o novo código gerado.

Micheus meu código ta assim
function TF_LANCAMENTO_PROJETO.incrementa_item: string;
var
  novo_item :Integer;
begin
      //**para auto incremento do item por cod_projeto_lancamento**//
    dm.sdsLancamentoItem.Close;
    dm.sdsLancamentoItem.CommandText:=´select max(item) as item ´ +
                                ´from lancamento_projeto ´ +
                                ´where cod_projeto_lancamento = :cod_projeto_lancamento´;
    dm.sdsLancamentoItem.ParamByName(´cod_projeto_lancamento´).AsString:=projeto.Text;
    dm.sdsLancamentoItem.Open;
    novo_item:=dm.sdsLancamentoItem.fieldbyname(´ITEM´).AsInteger+1;
    item.Text:=IntToStr(novo_item);
    dm.sdsLancamentoItem.Close;
end;

Ta funcionando só que está pulando de dois em dois ficando assim:
1
1
2
2
3
3
4
4
Ele fica repetindo o número mais uma vez.
Tem como acertar?
Tem como colocar isso num SP? Como faço?


GOSTEI 0
Micheus

Micheus

21/12/2007

- Observei que vc tem esta linha: [i:07af9bb1de]item.Text:=IntToStr(novo_item);[/i:07af9bb1de]
donde penso que vc está obtendo o código e mostrando na tela antes mesmo de concluir a inclusão dos novos dados. Esta atitude pode não garantir a existência de um único código, já que se mais que um usuário estiverem editando o mesmo registro, podem obter o mesmo número. O ideal é que este número seja apenas obtido no momento da gravação;

- Observei também que vc não atribui o valor obtido ao resultado da sua função [i:07af9bb1de]incrementa_item[/i:07af9bb1de]; O que vc está fazendo com o valor retornado pela função?

Quanto a esta estranha duplicação, não teria como dar um palpite sem saber como vc está tratando/gravando esta informação.
Por acaso, após gravar a informação vc está ´comitando´ a transação?

Quanto a colocar em uma SP, poderia sim. Qual banco vc está utilizando?
Basicamente vc criaria ela, definindo um parâmetro de entrada ([i:07af9bb1de]cod_projeto_lancamento[/i:07af9bb1de]) e um de saída ([i:07af9bb1de]ITEM[/i:07af9bb1de]).

Se sua intenção com esta numeração do ITEM ser seqüêncial para cada lançamento, vale lembrar que, caso seja excluído algum destes itens posteriormente, haverá uma lacuna na seqüência.

Abraços


GOSTEI 0
Jpauloss

Jpauloss

21/12/2007

- Observei que vc tem esta linha: [i:b7894fbdcf]item.Text:=IntToStr(novo_item);[/i:b7894fbdcf] donde penso que vc está obtendo o código e mostrando na tela antes mesmo de concluir a inclusão dos novos dados. Esta atitude pode não garantir a existência de um único código, já que se mais que um usuário estiverem editando o mesmo registro, podem obter o mesmo número. O ideal é que este número seja apenas obtido no momento da gravação; - Observei também que vc não atribui o valor obtido ao resultado da sua função [i:b7894fbdcf]incrementa_item[/i:b7894fbdcf]; O que vc está fazendo com o valor retornado pela função? Quanto a esta estranha duplicação, não teria como dar um palpite sem saber como vc está tratando/gravando esta informação. Por acaso, após gravar a informação vc está ´comitando´ a transação? Quanto a colocar em uma SP, poderia sim. Qual banco vc está utilizando? Basicamente vc criaria ela, definindo um parâmetro de entrada ([i:b7894fbdcf]cod_projeto_lancamento[/i:b7894fbdcf]) e um de saída ([i:b7894fbdcf]ITEM[/i:b7894fbdcf]). Se sua intenção com esta numeração do ITEM ser seqüêncial para cada lançamento, vale lembrar que, caso seja excluído algum destes itens posteriormente, haverá uma lacuna na seqüência. Abraços

Micheus meu botão de gravar está assim
procedure TF_LANCAMENTO_PROJETO.gravarClick(Sender: TObject);
begin
  if (projeto.Text=´´) or (grupo.text=´´) or (cod.Text=´´) or (qt.Text=´´) then begin ShowMessage(´Preencha dados básicos!´); exit end else begin
   Try
    transacao.TransactionID:=1;
    transacao.IsolationLevel:= xilREPEATABLEREAD;
    dm.Conexao.StartTransaction(transacao);
    dm.sdsLancamento.Close;
    dm.sdsLancamento.CommandText:=´insert into lancamento_projeto (cod_projeto_lancamento,´ +
                            ´cod_grupo_fk, cod_ordenado_m, quantidade_m,´+
                            ´total, item) values (:cod_projeto_lancamento, ´ +
                            ´:cod_grupo_fk, :cod_ordenado_m, :quantidade_m, :total, :item)´;
    dm.sdsLancamento.ParamByName(´cod_projeto_lancamento´).AsString:=projeto.Text;
    dm.sdsLancamento.ParamByName(´cod_grupo_fk´).AsString:=grupo1.Text;
    dm.sdsLancamento.ParamByName(´cod_ordenado_m´).AsString:=cod.Text;
    dm.sdsLancamento.ParamByName(´quantidade_m´).AsString:=qt.Text;
    dm.sdsLancamento.ParamByName(´total´).AsFloat:=StrToFloat(total.Text);
    dm.sdsLancamento.ParamByName(´item´).AsString:=item.Text;
    incrementa_item;{**para fazer auto incremento do campo ´ITEM´**}
    dm.sdsLancamento.ExecSQL;
    dm.Conexao.Commit(transacao);

    grupoChange(Sender);

Except
  on Exc:Exception do
  Begin
    ShowMessage(´Ocorreu um erro na tentativa de inclusão de registro:´+Exc.Message);
    dm.Conexao.Rollback(transacao);
  end;
end;
end;
end;

E a função é essa que postei.
O banco de dados que utilizo é firebird2.0
Com relação ao que vc disse
Se sua intenção com esta numeração do ITEM ser seqüêncial para cada lançamento, vale lembrar que, caso seja excluído algum destes itens posteriormente, haverá uma lacuna na seqüência.

Tem jeito de quando deletar um registro fazer um update para alterar todas as sequencias gravadas?
Valeu, fico no aguardo.


GOSTEI 0
Micheus

Micheus

21/12/2007

...
    dm.sdsLancamento.ParamByName(´item´).AsString:=item.Text;
    incrementa_item;{**para fazer auto incremento do campo ´ITEM´**}
    dm.sdsLancamento.ExecSQL;
...
em algum outro momento vc inicializa [i:9e948116f3]item.Text[/i:9e948116f3]?
é que como está seu código, se vc em algum outro momento inicializou ele, poderia ocorrer o seguinte:
- vc inicializa [i:9e948116f3]item.Text[/i:9e948116f3], logo ele recebe o texto ´1´;
- daí, vc atribui este valor ao parâmetro antes de gravar o registro;
- então, vc chama a funçao [i:9e948116f3]incrementa_item[/i:9e948116f3] que irá obter o máximo e somar 1, o que neste caso, ainda será retornado ´1´ e atribuirá ao [i:9e948116f3]item.Text[/i:9e948116f3];
- em seguida vc grava o registro, e o campo ITEM terá o valor ´1´ no banco;
próxima inclusão, observando o código que aqui está:
- da inclusão anterior, [i:9e948116f3]item.Text[/i:9e948116f3] ficou com o texto ´1´;
- daí, vc atribui este valor ao parâmetro antes de gravar o registro;
- então, vc chama a funçao [i:9e948116f3]incrementa_item[/i:9e948116f3] que irá obter o máximo e somar 1, o que neste caso, retornará ´2´ e atribuirá ao [i:9e948116f3]item.Text[/i:9e948116f3];
- em seguida vc grava o registro, e o campo ITEM terá o valor ´1´ no banco, já que [i:9e948116f3]item.Text[/i:9e948116f3] coninha ´1´ antes de vc chamar a funçao [i:9e948116f3]incrementa_item[/i:9e948116f3] (como mencionei na linha anterior);

Neste cenário, temos gravados dois itens ´1´!

Ou vc obtém o valor máximo antes de gravar o registro e atribui ele ao parâmetro, ou então vc obtém ele ao criar o novo registro para edição e não chama a funçao [i:9e948116f3]incrementa_item[/i:9e948116f3] na hora de gravar, há que [i:9e948116f3]item.Text[/i:9e948116f3] já conterá o nº do item desejado.


GOSTEI 0
POSTAR