Verificar se registro já existe

Delphi

29/08/2010

Pessoal

Estou tentando usar o ClientDataSet1.findKey mas não estou conseguindo, ele informa o
erro 'Unknown ISC error 0'.
Gostaria de saber como verifico se a venda já existe, e se existir, trazê-la.

...

With dm do
 Begin
  If TableVenda.findkey([TableVendaDocumento.value,TableVendaNumero.value]) then
     Begin
       M:=TableVendaDocumento.value;
       R:=TableVendaNumero.Value;
       TableVenda.cancel;
       TableVenda.FindKey([M,R]);
       venda(Db1,Db2,Db3,EditDocumento,EditNumero,Editdata,DbGridVenda);
       Db1.SetFocus;
     end
   Else
     Begin
       venda(Db1,Db2,Db3,EditDocumento,EditNumero,Editdata,DbGridVenda);
       TableVendaData.Value:=Date;
       Db1.SetFocus;
     end;
   end;


Li na internet que preciso setar o indice, mas o indice é a própria chave 'Documento e Numero'.
Caso precisasse setar um indice no ClientDataSet como seria ?.

Grato.


Marcos Roberto

Marcos Roberto

Curtidas 0

Respostas

Marco Salles

Marco Salles

29/08/2010

Pessoal

Estou tentando usar o ClientDataSet1.findKey mas não estou conseguindo, ele informa o
erro 'Unknown ISC error 0'.
Gostaria de saber como verifico se a venda já existe, e se existir, trazê-la.

...

With dm do
 Begin
  If TableVenda.findkey([TableVendaDocumento.value,TableVendaNumero.value]) then
     Begin
       M:=TableVendaDocumento.value;
       R:=TableVendaNumero.Value;
       TableVenda.cancel;
       TableVenda.FindKey([M,R]);
       venda(Db1,Db2,Db3,EditDocumento,EditNumero,Editdata,DbGridVenda);
       Db1.SetFocus;
     end
   Else
     Begin
       venda(Db1,Db2,Db3,EditDocumento,EditNumero,Editdata,DbGridVenda);
       TableVendaData.Value:=Date;
       Db1.SetFocus;
     end;
   end;


Li na internet que preciso setar o indice, mas o indice é a própria chave 'Documento e Numero'.
Caso precisasse setar um indice no ClientDataSet como seria ?.

Grato.


so uma curiosidade ... Vc esta utilizando dois campos para a pesquisa Porque ??? TableVendaNumero Não é Unico ??? Ou mesmo TableVendaDocumento tb não é unico ??? Porque que tem que encontrar os dois Juntos ???   Para setar este indice composto em tempo de designed ( tb da para fazer isto em RumTime ) Vc faz No Objecto Ispector selecione IndexDelfs .. clique na reticencias Na Caixa Editing clique no Botão Novo No Objecto Inspector deste Novo Item Selecione as proproiedades que vc quer .. de imediato são elas Fields >> Escreva os Nomes dos Campos separados por ponto e virgula Name >> Escolha um Nome para este Indice Veja que existem outras Opçoes interessantes em  options , vc define a caracteristica deste indice   No seu projeto qnd vc quiser usar este Indice vc faz   NomeDoSeiCds.IndexName:='NomeEscolhidoParaIndice';
GOSTEI 0
Pjrm1470

Pjrm1470

29/08/2010

Existe duas maneiras de se fazer uma procura por um registro em um DataSet. - FindKey() - Locate()   Bem... você disse que não está conseguindo utilizar o findKey. Ja tentou usar o locate()? Não sei dizer como solucionar este erro, mas sei que posso lhe dar outra alternativa, pois nunca usei o findKey. sempre utilizo o Locate.   Normalmente quando mandamos procurar por alguma coisa, mandamos uma referencia e um valor de procura. Como a tabela vai saber qual valor você quer achar se você so passa as referências? rs.
if TableVenda.Locate('VendaDocumento', ValorDeBusca, []) then
ou
if TableVenda.Locate('VendaNumero', ValorDeBusca, []) then
  Fique a vontade para perguntar. Att, pjrm1470.
GOSTEI 0
Marcos Roberto

Marcos Roberto

29/08/2010

Marco Antonio

Fiz como vc falou, criei o indice e ainda não resolveu.
A tabela tem duas chaves que pode ser documento=NC e Numero='0001' ou Documento='NF' e Numero='0001'.
NC Nota ao Consumidor e NF Nota Fiscal para pessoa Juridica.

Este metodo funcionava qdo usava com paradox, agora no Firebird esta com este problema.
...


PJRM1470

Posso usar o Locate, mas como passo as duas chaves no locate ???? já tentei e dá erro no sintaxe.
....



grato pessoal


GOSTEI 0
Pjrm1470

Pjrm1470

29/08/2010

Tente utilizar o Filter e Filtered do DataSet. Assim você consegue filtrar por várias condições. Faça o teste e me diga.
GOSTEI 0
Marco Salles

Marco Salles

29/08/2010

Marco Antonio

Fiz como vc falou, criei o indice e ainda não resolveu.
A tabela tem duas chaves que pode ser documento=NC e Numero='0001' ou Documento='NF' e Numero='0001'.
NC Nota ao Consumidor e NF Nota Fiscal para pessoa Juridica.

Este metodo funcionava qdo usava com paradox, agora no Firebird esta com este problema.
...


PJRM1470

Posso usar o Locate, mas como passo as duas chaves no locate ???? já tentei e dá erro no sintaxe.
....



grato pessoal


bem ... se vc criou esses indices corretamente   qnd vc fez   Seucds.IndexName:='SeuIndiceCompostoCriado';   Agora para usar o FindKey vc simplesmente faz   if cds.FindKey([edit1.Text,edit2.Text]) then   qualquer coisa else  outra coisa   Onde Edit1.text , edit2.text contem o dado que vc esta procurando respectivamente   Aqui a busca é simultanea e é END ... Ou os Dois ou nada Feito   entendeu ???
GOSTEI 0
Eriley Barbosa

Eriley Barbosa

29/08/2010

Não precisa usar o Findkey, pode usar o Locate com VarArrayOf, exemplo: DataSet.Locate('CAMPO1;CAMPO2', VarArrayOf(['String','String2']), []); With dm do
 Begin
  If TableVenda.Locate('Documento;Numero', VarArrayOf([TableVendaDocumento.value,TableVendaNumero.value]), []) then
     Begin
       M:=TableVendaDocumento.value;
       R:=TableVendaNumero.Value;
       TableVenda.cancel;
       TableVenda.Locate('Documento;Numero', VarArrayOf([M,R]), []) ;
       venda(Db1,Db2,Db3,EditDocumento,EditNumero,Editdata,DbGridVenda);
       Db1.SetFocus;
     end
   Else
     Begin
       venda(Db1,Db2,Db3,EditDocumento,EditNumero,Editdata,DbGridVenda);
       TableVendaData.Value:=Date;
       Db1.SetFocus;
     end;
   end;
GOSTEI 0
Marco Salles

Marco Salles

29/08/2010

eu comentei do findKey pq o autor do tópico o usa . Resta comentar que o Locate funciona mas so é recomendável para pequenos Range de dados do ClientDataSet. Para Volumes maiores de dados é alta perfomace que se utilize Indices em Memória juntamente com os métodos SetKey seguido do GotoKey .
GOSTEI 0
Marcos Roberto

Marcos Roberto

29/08/2010


Eriley

Na linha

" If TableVenda.Locate('Documento;Numero',VarArrayOf([TableVendaDocumento.value,TableVendaNumero.value]),[]) then"

está dando os seguintes erros

[DCC Error] untVenda.pas(217): E2066 Missing operator or semicolon
[DCC Error] untVenda.pas(217): E2001 Ordinal type required
[DCC Error] untVenda.pas(217): E2010 Incompatible types: 'Integer' and 'AnsiString'


Tô sem entender nada !!!

GOSTEI 0
Leonardo Bertolini

Leonardo Bertolini

29/08/2010

Bom, não conheço a estrutura da sua aplicação mas vou sugeria uma alternativa ao problema.

Se vc quer verificar se a venda já existe, crie uma função que de um select no banco passando na cláusula where os codigos referente a venda.

Vc também pode rodar um loop no ClientDataSet e testar os campos para ver se algum registro bate com a venda.

Bom, lógico isso depende do tamanho da sua aplicação e da quantidade de registros envolvidos nessa tabela.

espero ter ajudado, abraços.

twitter.com/leobertolini
GOSTEI 0
Marcos Roberto

Marcos Roberto

29/08/2010

Leonardo

Pensando no que vc me passou, gostaria de tirar esta outra dúvida:

No formulario de Vendas os DbEdit´s estão relacionados com a CDSVenda, ou seja DBedit1 é o CDSVendaNUMERO.value quando da ativação do form um insert é feito neste CDS, então teremos um ponteiro indicando um novo registro.
Agora, quando usar a função para verificar se esta venda já existe e retornar um null o formulário perderá as informações já digitadas não é.


1) Poderia então eu fazer esta função dando o select em outro CDS para não bagunçar este form????
2) Como normalmente é feito esses forms ?: colocamos DBEdit´s ou simplesmente Edit´s e depois atribuir
todos Edit´s para a tabela e dar o post.
 

Grato 


GOSTEI 0
Leonardo Bertolini

Leonardo Bertolini

29/08/2010

Bom Marcos seguinte,
Existem várias formas de exibir dados pro usuário, alguns de desenvolvedores preferem utilizar simples edit's e atribuir o valor do campo ao edit....  outros preferem componentes DB que ja trazem direto o valor do campo.
Acredito que a primeira opção tenha uma performance melhor, mas dependendo do tamanho da sua aplicação torna-se irrelevante.
Quanto a sua verificação se a venda já existe, com certeza seria melhor usar um outro DataSet para verificar se a venda existe (nao usar os mesmo DataSet que esta relacionado aos edit's do form).

Qual tipo de conexão ao BD vc utiliza ?  ADO ? DBExpress ? Zeos ?  qual BD é ?

GOSTEI 0
Leonardo Bertolini

Leonardo Bertolini

29/08/2010

Completando a resposta.... 

Assim se este outro DataSet não retornar nenhum registro vc sabe que a venda não existe, e ai vc pode fazer o que quiser dependendo do resultado.
Como tirar do modo de inserção o seu ClientDataSet
CDS.Cancel;
GOSTEI 0
Marcos Roberto

Marcos Roberto

29/08/2010

Leonardo

Valeu pela dica, vou verificar se o registro existe noutra CDS.

Uso Delphi 2010, DBExpress e Firebird.

SqlConnection, TClientDataSet, TSqlDataSet, TDataSetProvider e DataSource


Abraço.



Cara, outro problema: Quando insiro o terceiro item da venda dá um erro de chave violada, sendo que na tabela tem o seguinte trigger;

AS BEGIN
      IF(NEW."CODIGO" IS NULL) THEN NEW."CODIGO" = GEN_ID("GEN_TITEMVEN_CODIGO",1);
    END

Onde preciso mexer para fazer valer este trigger, com as outras tabelas sem mestre-detalhe não dão este erro.


GOSTEI 0
Leonardo Bertolini

Leonardo Bertolini

29/08/2010

Cara...  vi que vc usa a trigger para gerar a um sequencial....  mas me manda a estrutura da sua tabela informando quais sao as chaves primarias. ou se é so uma.
GOSTEI 0
Eriley Barbosa

Eriley Barbosa

29/08/2010

Quais os tipos das variaveis M e R? Quais os tipos dos campos Documento e Numero?
GOSTEI 0
Marcos Roberto

Marcos Roberto

29/08/2010


Leonardo

Chave Primaria DOCUMENTO e NUMERO;


CREATE TABLE TVENDAS (
    DOCUMENTO      CHAR(3),
    NUMERO         VARCHAR(6),
    TIPOVENDA      INTEGER,
    DATA           DATE,
    NUMEMPRESA     CHAR(1),
    NUMCFOP        CHAR(4),
    CONF           T_YESNO /* CHAR(1)  */,
    PARCELA        INTEGER,
    DTENTREGA      DATE,
    QTDNOTA        FLOAT,
    QTDENTR        FLOAT,
    CUPOM          VARCHAR(6),
    PAGAMENTO      INTEGER,
    NUMOCCURSITEM  INTEGER,
    CLIENTE        INTEGER,
    VENDEDOR       INTEGER,
    DESCONTO       DOM_VALOR /* DECIMAL(15,2) */,
    VRLDESCONTO    DOM_VALOR /* DECIMAL(15,2) */,
    TROCO          DOM_VALOR /* DECIMAL(15,2) */,
    RECEBIDO       DOM_VALOR /* DECIMAL(15,2) */,
    VALOR          DOM_VALOR /* DECIMAL(15,2) */,
    TOTAL          DOM_VALOR /* DECIMAL(15,2) */,
    EMDINHEIRO     DOM_VALOR /* DECIMAL(15,2) */,
    EMCHEQUE       DOM_VALOR /* DECIMAL(15,2) */,
    EMCARTAO       DOM_VALOR /* DECIMAL(15,2) */,
    EMTICKET       DOM_VALOR /* DECIMAL(15,2) */
);


Chave Primaria CODIGO


CREATE GENERATOR "GEN_TITEMVEN_CODIGO";

CREATE TABLE TITEMVEN (
    CODIGO        INTEGER,
    ITEM          INTEGER,
    DOCUMENTO     CHAR(3),
    NUMERO        VARCHAR(6),
    CODPRODUTO    FLOAT,
    QUANTIDADE    FLOAT,
    DATA          DATE,
    OBS           VARCHAR(25),
    DESCRPRODUTO  VARCHAR(50),
    CONF          FLOAT,
    DESCONTO      INTEGER,
    PRODUTO2      VARCHAR(15),
    CUPOM         VARCHAR(6),
    NUMNOTA       INTEGER,
    TOTAL         DOM_VALOR /* DECIMAL(15,2) */,
    CUSTO         DOM_VALOR /* DECIMAL(15,2) */,
    VLRDESCONTO   DOM_VALOR /* DECIMAL(15,2) */
);

vlw;

GOSTEI 0
Marcos Roberto

Marcos Roberto

29/08/2010

Eriley

segue;
procedure TFrmVenda.EditNumeroExit(Sender: TObject);
Var
M:String;
R:String;
VarArrayOF :array[1..2] of string;
begin

dm.TableVendaNUMERO.Value := Zeros(dm.TableVendaNUMERO.Value,6); ///preenche zeros a esquerda
dm.TableVenda.IndexName   := 'IDX_DOC';

With dm do
 Begin
  If TableVenda.FindKey([TableVendaDocumento.value,TableVendaNumero.value]) then
     Begin
       showmessage('ja existe');
       M:=TableVendaDocumento.value;
       R:=TableVendaNumero.Value;
       TableVenda.cancel;
       TableVenda.FindKey([M,R]);
       venda(Db1,Db2,Db3,EditDocumento,EditNumero,Editdata,DbGridVenda);
       Db1.SetFocus;
     end
   Else
     Begin
       showmessage('Nova Venda');
       venda(Db1,Db2,Db3,EditDocumento,EditNumero,Editdata,DbGridVenda);
       TableVendaData.Value:=Date;
       Db1.SetFocus;
     end;
   end;
end;

Grato;

GOSTEI 0
Eriley Barbosa

Eriley Barbosa

29/08/2010

Você conseguiu resolver isso?
GOSTEI 0
Marcos Roberto

Marcos Roberto

29/08/2010


 Eriley

 Resolvi com o locate conforme vc enviou.
 Preciso dar como "Resolvido" este tópico e não estou conseguindo.

 Valeu pela Ajuda

GOSTEI 0
POSTAR