GARANTIR DESCONTO

Fórum Campo Serial #26399

16/09/2005

0

Criei um campo tipo serial no meu BD e tudo bem ? Porém quando vou mandar gravar na tabela através do sistema eu não defino valor para este campo achando que quem deve fazê-lo é o BD. Porém ele me retorna erro dizendo que este campo não pode ser gravado vazio. Alguém sabe como
resolver isso ?


Grande abraço.


Winfor

Winfor

Responder

Posts

16/09/2005

Bon Jovi

Isso não é normal acontecer, o q está fazendo de diferente? Está usando o q pra inserir o registro? Isso pode ser uma característica do componente que vc está usando.

Ex. normal:

CREATE TABLE tabela
(
sequencial serial NOT NULL,
descricao varchar(50),
CONSTRAINT pk_tabela PRIMARY KEY (sequencial)
);

INSERT INTO tabela (descricao) VALUES (´aaa´);

Executou tudo ok.

SELECT * FROM tabela;

Retornado:

sequencial;descricao
1;´aaa´


Responder

Gostei + 0

17/09/2005

Winfor

Na verdade, estou utilizando os componentes da Devexpress e utilizando os comando normais de inclusão de registros. Append, post, e applyupdates.
O problema ocorre quando confirmo a inclusão do registro. E eu nem coloquei um componente ligado ao campo código para não haver problema.
A única coisa que fiz de anormal, foi modificar o tipo do campo na tabela após a mesma ter sido criada. Ou seja, ele estava como integer e eu passei para Serial.
No programa de manipulação do BD que é o EMS Manager funciona normalmente.


Responder

Gostei + 0

17/09/2005

Bon Jovi

Vc deverá dar Refresh após um ApplyUpdates, para que o componente possa saber que o campo SERIAL foi atribuído pelo SEQUENCE no servidor. Ex.:

procedure TfrmTeste.btnTesteClick(Sender: TObject);
var
  i: integer;
begin
  ADOCommand1.CommandText := ´CREATE TABLE teste (id_teste serial PRIMARY KEY, descricao VARCHAR(10))´;
  ADOCommand1.Execute;

  ADODataSet1.CommandText := ´SELECT id_teste, descricao FROM teste´;
  ClientDataSet1.Open;

  for i := 1 to 3 do
  begin
    ClientDataSet1.Append;
    ClientDataSet1.FieldByName(´descricao´).AsString := ´teste_´ + IntToStr(i);
    ClientDataSet1.Post;
    ClientDataSet1.ApplyUpdates(-1);
    ClientDataSet1.Refresh;
  end;

  ClientDataSet1.First;
  
  while not ClientDataSet1.Eof do
  begin
    ShowMessage(´ID_TESTE = ´ + ClientDataSet1.FieldByName(´id_teste´).AsString);
    ClientDataSet1.Next;
  end;
end;

Gravou no banco e retornou: 1, 2, 3


Responder

Gostei + 0

17/09/2005

Bon Jovi

Podem haver outras saídas mais otimizadas, pois não sou de usar o tipo ´SERIAL´. Eu prefiro usar SEQUENCE (CREATE SEQUENCE), ou seja, desamarrado do campo, assim ganha-se mais controle.


Responder

Gostei + 0

18/09/2005

Winfor

Amigo Bon Jovi

Na verdade, quando eu modifiquei o campo para serial ele criou um item na seção sequences do BD. Desta forma:

CREATE SEQUENCE ´public´.´professores_wpro_codigo_seq´
INCREMENT 1 MINVALUE 1
MAXVALUE 2147483647 START 5
CACHE 1;

Imagino que este sequence se assemelha ao campo Generator do Interbase, mas não sei como buscá-lo em tempo de execução. Na edição desta seguencia ele me mostra quais os valores aceita acima e qual será o próximo, mas não tô sabendo buscar isso de dentro do programa.
Vc busca na hora de postar o código ? Como ?

Estou estudando o manual do Postgres mas ainda não cheguei lá.

Valeu pela força. Grande abraço.


Wellington.


Responder

Gostei + 0

18/09/2005

Winfor

Aliás, estou tentando buscar este valor assim:

Wdm_cadastro.Qry_auxCadastro.Close;
Wdm_cadastro.Qry_auxCadastro.SQL.Add(´SELECT nextval(´public´.´sequence´.´professores_wpro_codigo_seq´) AS ULTIMOCODIGO´);
Wdm_cadastro.Qry_auxCadastro.Open;
Wdm_cadastro.Qry_auxCadastro.ExecSQL;

Nem sei se está certo, pq estou começando agora com SQL, mas ele erro se coloco public, se coloco sequence e se não coloco nada em nextval.

Vc sabe a sintaxe correta pra isso aí :)

Valeu mais uma vez !!!


Responder

Gostei + 0

18/09/2005

Bon Jovi

Sim, ele cria, mas se vc agora está querendo atribuir manualmente, por que está usando o tipo SERIAL?

Faz normal:

CREATE TABLE cliente (id_cliente numeric(15) primary key, nome_cliente varchar(50));

CREATE SEQUENCE sequencial_cliente MINVALUE 1;

E no Delphi atribui ao campo:

SELECT nextval(´sequencial_cliente´) AS proximo


Responder

Gostei + 0

18/09/2005

Winfor

Na verdade, não estou querendo atribuir manualmente. Como ele está me retornando erro falando que o campo não pode ficar vazio. Estou tentando buscar em tempo de execução qual será o próximo código e atribí-lo no post. Assim ele não dará mais este erro, por isso que estava usando a instrução Sql acima. Mas da forma que vc colocou ele fala que não existe o campo.
Para dar um select na tabela a partir da Query, ele somente aceitou quando eu coloquei assim:
SELECT * FROM ´public´.´professores´

De outra forma, sem o public ele fala que não existe a tabela.

Por isso que ao buscar o próximo código usei aquela instruição acima.


Continuo tentando.... aqui...

Obrigado pela paciência migão...


Responder

Gostei + 0

19/09/2005

Bon Jovi

Usou o Refresh após o ApplyUpdates como no exemplo? Pois isso funciona.


Responder

Gostei + 0

19/09/2005

Bon Jovi

Se não estiver funcionando com sua aplicação, execute meu exemplo completo em uma aplicação nova e verá que funciona. Daí vc vai vendo o q tem de diferente na sua aplicação.

Só não coloquei a parte de conexão nesse exemplo, em que usei conexão ADO com driver ODBC.


Responder

Gostei + 0

19/09/2005

Winfor

É. Fiz uma nova aplicação, segui bem de perto os passos que vc fez, a diferença é que estou usando o Zeos 6.5.1 que tem protocolo até o Postgres 7.4 enquanto estou usando o 8.01.
Fiz uma nova aplicação, porém ao dar o Post, ele retorna o mesmo erro, mesmo dando o Refresh junto com o Apply. Mudei o Refresh de lugar, tentei outra atualização e não deu certo.
E na instrução SQL fala que não existe o campo sequencial que estou me referindo. Tentei usando ´public´, ´public´.´sequence´.nomedocampo, somente o nome do campo e ele continua não localizando o mesmo no BD.
Acho que o caminho é por aqui, tenho só que arranjar uma forma na sintaxe SQL de me comunicar com este campo serial e pegar o próximo valor dele. Fazendo isto posso atribuí-lo a um Dbedit e mandar postar pq aí eu sei que funciona. Pois já fiz o teste atribuindo diretamente um valor ao campo.

Continuando minha saga, obrigado pela atenção e ajuda.


Responder

Gostei + 0

19/09/2005

Bon Jovi

Se não usar SERIAL e criar o SEQUENCE solto já seria uma solução imediata.

Coloque o trecho do seu código aqui, DFM dos componentes relacionados tb. Assim posso ver o q está fazendo. Coloque tudo que for diretamente relacionado, script da tabela tb.


Responder

Gostei + 0

23/09/2005

Winfor

Olá, Bon Jovi

Estive fora por 3 dias por isso sumi.
Eu utilizo um Trial da EMS Manager PostgresSQL para gerenciar e criar as tabelas, índices e outros do BD. Por isso não preciso necessariamente postar instruções SQL dentro da aplicação para dar manutenção do BD.
Na tela em questão do problema do campo serial, utilizo componentes da Devexpress normalmente, então coloco componentes cxdbEdit, CxMaskEdit, etc...
Utilizo tb o componente de menu da MaxComponets para o menu tipo outlook

Todos componentes tipo padrão que não dão interferências.

Então, após conectado o BD e criadas as tabelas com os Querys, clientDatasets, providers e DataSource. E criados os respectivos Tfields, dou um insert ou append e após a edição dos campos faço a rotina abaixo.

if MessageDlg(´Confirma a gravação dos dados deste funcionário ?´, mtConfirmation, [mbYes, mbNo], 0) = mrYes then
begin
//CxTextEdit2.Text := intToStr(Wdm_cadastro.CDfuncionarioWPRO_CODIGO.value);
Try //Se a tabela está inserindo
If (Wdm_cadastro.CDfuncionario.State = DsInsert) then
Begin
Ufuncoes.WBotoes(Wdm_cadastro.DSfuncionario.DataSet,6);
end
else
ShowMessage(´Falha na atualização, o arquivo não está em modo de alteração !´);
Wdm_cadastro.CDfuncionario.ApplyUpdates(-1);
Wdm_cadastro.CDfuncionario.Refresh;
except
ShowMessage(´Erro de gravação´);
end;
At_botoes;
end;

Tudo dentro do padrão que a maioria está acostumada.

Dentro do EMS Manager os campos já estão definidos como serial. A única coisa que eu acho que poderia fazer alguma diferença, é o fato do campo codigo ter sido criado como Integer e depois eu o passai para Serial.
Se precisar de mais aguma informação é só falar.


Brigado migão...


Responder

Gostei + 0

23/09/2005

Winfor

Outro detalhe me chamou a atenção hoje aqui, ao fazer um outro exemplo simples usando clientDataset, query, provide, Datasource e Zeos Zconection, e os componentes padrão do Delphi.
2 DbEdit´s e um Dbnavigator.

Além de dar o mesmo erro de não aceitar o campo código vazio, se eu preencher o campo código com algum número, ele não atualiza o contador serial da tabela.
Por exemplo:
Tabela de portadores: Codigo (serial), Descricao (Varchar(30)
Tabela Vazia.

Ao inserir um registro com o dbedit em branco dá erro.
Ao inserir um registro com o dbedit com valor = 1 ele aceita
Ao inserir um registro com o dbedit com valor = 2 ele aceita

Ao tentar inserir um registro pelo gerenciador EMS Manager ele começa a contagem novamente dos registros. Ou seja, começa do 1. Pode ???
Tá complicado...


Responder

Gostei + 0

23/09/2005

Bon Jovi

Vc está usando uma variedade de componentes de terceiros, infelizmente fica complicado pra eu ajudar em relação a eles, ainda mais sem ver o código completo do .pas, .dfm e script .sql.

Zeos já está bem estável com Midas?? Costumo sempre que possível usar os componentes mais padrões. Com ADO sei que funciona redondo. Se puder faz esse teste simples com ADO + ODBC. Ou poste um novo tópico mais específico: ´Campo Serial com Zeos + Midas´.


Responder

Gostei + 0

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar