Dúvida com Primary Key e Foreign Key
Estou tendo problemas para manipular Chave primaria e chave estrangeira. Estou usando os componentes dbExpress e Data Access para fazer a conexão:
SQLConnection -> SQLDataSet -> DataSetProvider -> ClientDataSet
Tenho as seguintes tabelas:
LOGIN
id_user integer NOT NULL Primary Key*
login varchar
senha varchar
DADOS
id_pess integer NOT NULL Primary Key*
id_user integer NOT NULL Foreign Key LOGIN
nome varchar
fone varchar
*Ambos tem uma Trigger de auto incremento antes do ´Insert´
Agora aí vão as dúvidas:
1)Quando vou gravar um registro na tabela LOGIN, ele diz que o compo ´id_user´ é requerido, mas como vou passar um valor sendo que o SGBD vai se encarregar de colocar o valor pra mim? Como faço para configurar ou pular isso?
2) Na tabela DADOS a mesma coisa, mas ainda tem o problemas da FOREIGN KEY. Quando vou gravar um registro, ele pede um valor pra chave estrangeira, mas quando vou dar um valor, no caso um valor válido da tabela LOGIN, ele da um erro de violação de chave. Como eu resolvo
isso?
Valew
SQLConnection -> SQLDataSet -> DataSetProvider -> ClientDataSet
Tenho as seguintes tabelas:
LOGIN
id_user integer NOT NULL Primary Key*
login varchar
senha varchar
DADOS
id_pess integer NOT NULL Primary Key*
id_user integer NOT NULL Foreign Key LOGIN
nome varchar
fone varchar
*Ambos tem uma Trigger de auto incremento antes do ´Insert´
Agora aí vão as dúvidas:
1)Quando vou gravar um registro na tabela LOGIN, ele diz que o compo ´id_user´ é requerido, mas como vou passar um valor sendo que o SGBD vai se encarregar de colocar o valor pra mim? Como faço para configurar ou pular isso?
2) Na tabela DADOS a mesma coisa, mas ainda tem o problemas da FOREIGN KEY. Quando vou gravar um registro, ele pede um valor pra chave estrangeira, mas quando vou dar um valor, no caso um valor válido da tabela LOGIN, ele da um erro de violação de chave. Como eu resolvo
isso?
Valew
Seu_madruga
Curtidas 0
Respostas
Kotho
04/04/2005
O seu problema de campo requerido é fácil de resolver... é que quando o campo é Primary, ele traz como required no delphi... basta mudar esta propriedade no FieldsEditor.
O problema de Key Violation ocorre, porque o campo está com a propriedade ProviderFlags como Key (e ele tem que estar assim mesmo). E, toda vez que tiver mais de um registro que esse campo possua o mesmo valor vai gerar esta exceção. Então, você pode jogar um valor (que pode ser uma variavel que seja incrementada) para burlar esse erro, já que você vai atribuir via trigger.
Tem uma propriedade no DataSetProvider chamada Constraints, mas essa eu nunca testei. Tente colocar como False antes de usar a opção anterior.
O problema de Key Violation ocorre, porque o campo está com a propriedade ProviderFlags como Key (e ele tem que estar assim mesmo). E, toda vez que tiver mais de um registro que esse campo possua o mesmo valor vai gerar esta exceção. Então, você pode jogar um valor (que pode ser uma variavel que seja incrementada) para burlar esse erro, já que você vai atribuir via trigger.
Tem uma propriedade no DataSetProvider chamada Constraints, mas essa eu nunca testei. Tente colocar como False antes de usar a opção anterior.
GOSTEI 0
Seu_madruga
04/04/2005
OK. Eu coloquei no campo do ClientDataSet com Required = False. Mas mesmop assim, quando vou gravar, ele da uma mensagem de ´Field value required´ mas a mensagem mudou. Antes era ´Field id_user must have a value´ e agora ´Field value Required´. Não entendo isso?
GOSTEI 0
Kotho
04/04/2005
Mude no SQLQuery também. Na verdade a principal mudança tem que ser ai... o ClientDataSet tem que refletir as mesmas propriedades que a Query.
GOSTEI 0
Seu_madruga
04/04/2005
OK. Mas então eu preciso criar os objetos de campo tanto na query quanto no ClientDataSet?
GOSTEI 0
Kotho
04/04/2005
Eu conheço duas situações que os campos precisam estar no ClientDataSet: uma é quando se utiliza Master/Detail... outra quando é preciso criar algum evento para o campo...
Fora isso, eu nem incluo os campos no Client, pois só dá trabalho extra.
Fora isso, eu nem incluo os campos no Client, pois só dá trabalho extra.
GOSTEI 0
Seu_madruga
04/04/2005
Mas no meu caso, com o problema de campos requeridos, o que devo fazer? Crio os objetos de campo no SQLDataSet, no ClientDataSet ou nos dois para retirar a opção requerido no campo ID?
GOSTEI 0
Kotho
04/04/2005
no SQLDataSet...
GOSTEI 0
Seu_madruga
04/04/2005
Cara, ainda com o problema da Chave primária e usando apenas a tabela LOGIN. Não funciona. Vou escrever passo a passo o que eu fiz:
1) Tenho no form um SimpleDataSet, um DataSource e um DBGrid;
2) Tenho dois DBEdits que ligam os campos LOGIN e SENHA;
3) Dois botões, um tem o SimpleDataSet.INSERT e outro com POST e APPLYUPDATES;
4) Liguei a tabela LOGIN no SimpleDataSet.Connection;
5) Coloquei um comando SQL ´Select * from LOGIN´ no CommandText do SimpleDataSet.DataSet.CommandText;
6) Rodei a aplicação e quando vou dar um POST ou APPLYUPDATES aparece a msn:
´Field ID must have a value´
7) Faço um duplo clique no SimpleDataSet para criar os objetos de Campo
ID, LOGIN E SENHA;
8) Selecionei o Campo ID para trocar suas propriedades;
9) Coloco a opção do campo ID Required de True para False
Rodo a aplicação novamnte e aparece outra msn:
´Field value Required´
10) Troquei a opção do compo ID ´AutoGenerateValue´ para ´arAutoInc´
11) Em ProviderFlags coloquei a opção ´pfInKey´ como True
12) Nada ainda, continua com o erro! Não sei o que fazer!
O que eu faço? Não funciona, quem puder eproduzir o erro para ver aonde eu estou errando, eu agradeceria muito
Valew
1) Tenho no form um SimpleDataSet, um DataSource e um DBGrid;
2) Tenho dois DBEdits que ligam os campos LOGIN e SENHA;
3) Dois botões, um tem o SimpleDataSet.INSERT e outro com POST e APPLYUPDATES;
4) Liguei a tabela LOGIN no SimpleDataSet.Connection;
5) Coloquei um comando SQL ´Select * from LOGIN´ no CommandText do SimpleDataSet.DataSet.CommandText;
6) Rodei a aplicação e quando vou dar um POST ou APPLYUPDATES aparece a msn:
´Field ID must have a value´
7) Faço um duplo clique no SimpleDataSet para criar os objetos de Campo
ID, LOGIN E SENHA;
8) Selecionei o Campo ID para trocar suas propriedades;
9) Coloco a opção do campo ID Required de True para False
Rodo a aplicação novamnte e aparece outra msn:
´Field value Required´
10) Troquei a opção do compo ID ´AutoGenerateValue´ para ´arAutoInc´
11) Em ProviderFlags coloquei a opção ´pfInKey´ como True
12) Nada ainda, continua com o erro! Não sei o que fazer!
O que eu faço? Não funciona, quem puder eproduzir o erro para ver aonde eu estou errando, eu agradeceria muito
Valew
GOSTEI 0
Seu_madruga
04/04/2005
Sobe!!!
GOSTEI 0
Fred
04/04/2005
olha vc teria que passar um valor para o campo chave! tipow: 0 por exemplo, ai la no banco a trigger colocaria o valor certo do generator, o problema eh c vc for usar esse campo logo em seguida(tipow pra usar no seu detail) daria pau, pq o valor nao seria o correto, vc teria que dar um refresh no cds depois de gravar(e isso nao eh muito bom neh) bom eu ja passei por isso e o que fiz foi usar uma dica do Cantu na revista clube delphi!!!
ai vai a function:
no evento OnNewRecord ou outro semelhante vc coloca seudataSetCODIGO.AsInteger := AutoInc(´NOMEDOGENERATOR´);
e apague todas as triggers de autoincremento
ai vai a function:
function TfrmPadrao.AutoInc(gen : string): integer; var ResultSet : TCustomSQLDataSet; SQLstmt : string; begin result := 0; SQLstmt := ´select gen_id(´+gen+´,1) ´ + ´as VALOR from RDB$DATABASE;´; ResultSet := nil; try dm.SQLConnection1.Execute(SQLstmt, nil, @ResultSet); if Assigned(ResultSet) then Result := ResultSet.FieldByName(´VALOR´).AsInteger; finally ResultSet.Free; end; end;
no evento OnNewRecord ou outro semelhante vc coloca seudataSetCODIGO.AsInteger := AutoInc(´NOMEDOGENERATOR´);
e apague todas as triggers de autoincremento
GOSTEI 0
Seu_madruga
04/04/2005
Bacana! Vou implementar isso para ver mas e agora a outra dúvida para manipular Foreign Key?
GOSTEI 0
Seu_madruga
04/04/2005
olha vc teria que passar um valor para o campo chave! tipow: 0 por exemplo, ai la no banco a trigger colocaria o valor certo do generator, o problema eh c vc for usar esse campo logo em seguida(tipow pra usar no seu detail) daria pau, pq o valor nao seria o correto, vc teria que dar um refresh no cds depois de gravar(e isso nao eh muito bom neh) bom eu ja passei por isso e o que fiz foi usar uma dica do Cantu na revista clube delphi!!!
O problema é que eu não queria apagar as triggers de auto incremento nem precisar passar 0 para enganar o banco de dados, deve ter algum parametro que indica que meu campo ID é auto incremento no Banco e a aplicação não vai me pedir ele.
GOSTEI 0
Fred
04/04/2005
olha c tem eu nao achei?? ja tentei colocar no fields editor(la tem uma propriedade) mas nada!!! com IBDataSet eu sei que da!!! e da escolher ate o generator!!!
GOSTEI 0