GARANTIR DESCONTO

Fórum Problema para gerar um exception em uma trigger? #58396

13/06/2007

0

Pessoal, eu quero criar um exception em um trigger para nao repetir os mesmos dados mais de uma vez no banco de dados, mais esta repetindo os dados e nao esta disparando a trigger

Olhe a trigger
CREATE TRIGGER RESTRUCAO FOR FOLHA
ACTIVE BEFORE INSERT POSITION 0
AS
begin
  /* Trigger text */
  if ( Exists(Select * from folha WHERE id_sal = NEW.id_sal
  and funcionario = new.funcionario
  and data = new.data
  and descricao = new.descricao
  and valor = new.valor
  and P_D = new.P_D ) )
then 
  Exception RESTRICAO ´Atenção Usuário!!! Dados já consta cadastrado no Banco de Dados!´; 

end


O que esta errado nesta trigger?

Queria fazer uma unique mais nao estou conseguindo
Fiz assim a unique
alter table FOLHA
add constraint UNQ1_FOLHA
unique (ID_SAL,FUNCIONARIO,DATA,DESCRICAO,VALOR,P_D)


Mais acusa o seguinte erro

[color=red:8843f2a55f]Invalid insert or update value(s): object columns are
constrained - no 2 table rows can have duplicate column values.
attempt to store duplicate value (visible to active transactions) in unique index ´UNQ1_FOLHA´.
[/color:8843f2a55f]

Por isso fiz uma trigger


Estou usando firebird 2.0


Adriano_servitec

Adriano_servitec

Responder

Posts

13/06/2007

Adriano_servitec

Alias, estou mesmo querendo um select + ou - assim
procedure TFcalculo.BTrasnportarDadosClick(Sender: TObject);
var 
ibx : integer;
begin
  dm.qHolerith.close;
  dm.qHolerith.SQL.Clear;
  dm.qHolerith.SQL.Add(´Select select * from holerith A where Exists(select * from holerith B where B.id_sal = A.id_sal and B.funcionario = A.funcionario and B.data = A.data and B.descricao = A.descricao)´);
  dm.qHolerith.open;
  if dm.qHolerith.Bof and dm.qHolerith.Eof Then
      showmessage(´Atenção Usuário! Dados já cadastrados´)
  else
  For ibx :=0 to m3.Items.Count-1 do //começo for listbox1
  begin
    dm.qHolerith.Append;
    dm.qHolerith.fieldByName(´id_sal´).value:=dm.qfuncionariosid_sal.Value;
    dm.qHolerith.fieldByName(´funcionario´).AsString:=dm.qfuncionariosnome.asString;
    dm.qHolerith.fieldByName(´data´).AsString:=mdata.Text;
    dm.qHolerith.fieldByName(´id_formula´).value:=lb1.Items[ibx];
    dm.qHolerith.fieldByName(´descricao´).AsString := m3.Items[ibx];
    dm.qHolerith.fieldByName(´valor´).AsString := m2.Items[ibx];
    dm.qHolerith.Post;
  end; //final do for listbox1
  For ibx :=0 to lb2.Items.Count-1 do //começo for listbox2
  begin
    dm.qHolerith.Append;
    dm.qHolerith.fieldByName(´id_sal´).value:=dm.qfuncionariosid_sal.Value;
    dm.qHolerith.fieldByName(´funcionario´).AsString:=dm.qfuncionariosnome.asString;
    dm.qHolerith.fieldByName(´data´).AsString:=mdata.Text;
    dm.qHolerith.fieldByName(´id_formula´).value:=lb2.Items[ibx];
    dm.qHolerith.fieldByName(´descricao´).AsString := d1.Items[ibx];
    dm.qHolerith.fieldByName(´valor´).AsString := d3.Items[ibx];
    dm.qHolerith.Post;
  end; //final do for do listbox2
end;


Ou seja se ja tiver no banco de dados nao grava, grava apenas os que nao tem no banco de dados, entao resolvi unir a mesma tabela em dois selects com a funçao EXISTS, mais esta acusando erro na SQL.

Tambem fiz um teste na propriedade SQL do Query assim
select * from holerith A
where exists(select * from holerith B 
where B.id_sal = A.id_sal 
and 
B.funcionario = A.funcionario 
and
B.data = A.data 
and 
B.descricao = A.descricao)

E consegui ativar esta query, mais preciso que seja feito diretamente na unit e nao na propriedade SQL do Query.


Responder

Gostei + 0

14/06/2007

Emerson Nascimento

Queria fazer uma unique mais nao estou conseguindo Fiz assim a unique
alter table FOLHA
add constraint UNQ1_FOLHA
unique (ID_SAL,FUNCIONARIO,DATA,DESCRICAO,VALOR,P_D)
Mais acusa o seguinte erro [color=red:72238a7c58]Invalid insert or update value(s): object columns are constrained - no 2 table rows can have duplicate column values. attempt to store duplicate value (visible to active transactions) in unique index ´UNQ1_FOLHA´. [/color:72238a7c58] Estou usando firebird 2.0

Você não consegue criar a trigger porque já há valores duplicados na tabela. Exclua as duplicidades e tente criar a unique novamente.


Responder

Gostei + 0

14/06/2007

Adriano_servitec

Olah amigo, obrigado por responder, bom essa parte eu ja resolvi, mais a unique nao deixa eu incluir mais dados na mesma tabela.

Explico:

Tenho listbox que vao jogar valores para a tabela, entao se a unique estiver ativa, nao vai deixar repetir dados, no caso preciso excluir os dados para jogar os novos dados, por isso estou querendo fazer do jeito que mostei acima.

procedure TFcalculo.BTrasnportarDadosClick(Sender: TObject); var ibx : integer; begin dm.qHolerith.close; dm.qHolerith.SQL.Clear; dm.qHolerith.SQL.Add(´Select select * from holerith A where Exists(select * from holerith B where B.id_sal = A.id_sal and B.funcionario = A.funcionario and B.data = A.data and B.descricao = A.descricao)´); dm.qHolerith.open; if dm.qHolerith.Bof and dm.qHolerith.Eof Then showmessage(´Atenção Usuário! Dados já cadastrados´) else For ibx :=0 to m3.Items.Count-1 do //começo for listbox1 begin [b:ac9f71d888]delete from holerith where B.id_sal = A.id_sal and B.funcionario = A.funcionario and B.data = A.data and B.descricao = A.descricao[/b:ac9f71d888] dm.qHolerith.Append; dm.qHolerith.fieldByName(´id_sal´).value:=dm.qfuncionariosid_sal.Value; dm.qHolerith.fieldByName(´funcionario´).AsString:=dm.qfuncionariosnome.asString; dm.qHolerith.fieldByName(´data´).AsString:=mdata.Text; dm.qHolerith.fieldByName(´id_formula´).value:=lb1.Items[ibx]; dm.qHolerith.fieldByName(´descricao´).AsString := m3.Items[ibx]; dm.qHolerith.fieldByName(´valor´).AsString := m2.Items[ibx]; dm.qHolerith.Post; end; //final do for listbox1 For ibx :=0 to lb2.Items.Count-1 do //começo for listbox2 begin dm.qHolerith.Append; [b:ac9f71d888]delete from holerith where B.id_sal = A.id_sal and B.funcionario = A.funcionario and B.data = A.data and B.descricao = A.descricao[/b:ac9f71d888] dm.qHolerith.fieldByName(´id_sal´).value:=dm.qfuncionariosid_sal.Value; dm.qHolerith.fieldByName(´funcionario´).AsString:=dm.qfuncionariosnome.asString; dm.qHolerith.fieldByName(´data´).AsString:=mdata.Text; dm.qHolerith.fieldByName(´id_formula´).value:=lb2.Items[ibx]; dm.qHolerith.fieldByName(´descricao´).AsString := d1.Items[ibx]; dm.qHolerith.fieldByName(´valor´).AsString := d3.Items[ibx]; dm.qHolerith.Post; end; //final do for do listbox2 end;


Entao achei o correto fazer assim, mais nao estou conseguindo.

[b:ac9f71d888]Obs. Esse delete fiz a zoio, mais a ideia seria deletar conforme a condiçao where para nao excluir os demais que nao seja aquele.[/b:ac9f71d888]

Obrigado pela ajuda.


Responder

Gostei + 0

14/06/2007

Adriano_servitec

Pessoal, descobri o erro
Olhem como estava antes
dm.qHolerith.SQL.Add(´[color=red:9ad8c8d7cc]Select[/color:9ad8c8d7cc] select * from holerith A where Exists(select * from holerith B where B.id_sal = A.id_sal and B.funcionario = A.funcionario and B.data = A.data and B.descricao = A.descricao)´);


Olhem o correto
dm.qHolerith.close;
  dm.qHolerith.SQL.Clear;
  dm.qHolerith.SQL.Add(´select * from holerith where Exists(select * from holerith B where B.id_sal = id_sal and B.funcionario = funcionario and B.data = data and B.descricao = descricao)´);
  dm.qHolerith.open;


Erro no script do SQL :oops:


Responder

Gostei + 0

14/06/2007

Adriano_servitec

Nao deu certo nao, continua repetindo os valores, ai tentei usar uma SP assim:
SET TERM ^ ;

CREATE PROCEDURE UPD_INS_HOLERITH (
    id_sal integer,
    funcionario varchar(70),
    data date,
    descricao varchar(60),
    valor numeric(15,2),
    p_d char(1))
as
begin
  if (exists(
        select id_sal, funcionario, data, descricao, valor, p_d
        from holerith where (id_sal = :id_sal and funcionario = :funcionario
        and data = :data and descricao = :descricao and valor = :valor and p_d = :p_d)
            )) then
    update holerith
      set funcionario = :funcionario,
          data = :data,
          descricao = :descricao, 
          valor = :valor,
          p_d = :p_d
       where (id_sal=:id_sal);
   else
     insert into holerith (
       id_sal,
       funcionario,
       data,
       descricao,
       valor,
       p_d)
     values (
       GEN_ID(gen_holerith_id,1),
       :funcionario,
       :data,
       :descricao,
       :valor,
       :p_d);
end^

SET TERM ; ^

GRANT SELECT,INSERT,UPDATE ON HOLERITH TO PROCEDURE UPD_INS_HOLERITH;

GRANT EXECUTE ON PROCEDURE UPD_INS_HOLERITH TO SYSDBA;


Mais ao passar a SP pelo componente StoredProc, verifiquei na tabela e nada, continua repetindo os dados.

procedure TFcalculo.Button19Click(Sender: TObject);
var
ibx :integer;
begin
 For ibx :=0 to m3.Items.Count-1 do //começo for listbox1
  begin
    dm.spInsUpdHol.Close;
    dm.spInsUpdHol.Params[0].Value := dm.qfuncionariosid_sal.Value;
    dm.spInsUpdHol.Params[1].Value := dm.qfuncionariosnome.asString;
    dm.spInsUpdHol.Params[2].Value := mdata.Text;
    dm.spInsUpdHol.Params[3].Value := m3.Items[ibx];
    dm.spInsUpdHol.Params[4].Value := m2.Items[ibx];
    dm.spInsUpdHol.Params[5].Value := ´P´;
    dm.spInsUpdHol.ExecProc;
 end;
 For ibx :=0 to d1.Items.Count-1 do //começo for listbox2
  begin
    dm.spInsUpdHol.Close;
    dm.spInsUpdHol.Params[0].Value := dm.qfuncionariosid_sal.Value;
    dm.spInsUpdHol.Params[1].Value := dm.qfuncionariosnome.asString;
    dm.spInsUpdHol.Params[2].Value := mdata.Text;
    dm.spInsUpdHol.Params[3].Value := d1.Items[ibx];
    dm.spInsUpdHol.Params[4].Value := d3.Items[ibx];
    dm.spInsUpdHol.Params[5].Value := ´D´;
    dm.spInsUpdHol.ExecProc;
  end;
end;

Sera que eh por causa que estou jogando os valores de listbox para o banco de dados? Pq as vezes sao mais de um valor soh que o campo ID_SAL eh o que uso para fazer o update, mais nao posso deixa-lo como PK pois vai reperir esse campo varias vezes na tabela

Exemplo
id_sal----------funcionario----------data--------descricao----valor----pd
1---------------adriano---------------31/05/07--salario------1.000,00--p
1---------------adriano---------------31/05/07--inss------------80,00---d
2---------------pedro-----------------31/05/07--salario--------600,00--p
2---------------pedro-----------------30/06/07--salario--------600,00--p
...
...

Entao, se eu quiser arrumar o funcionario adriano no mes 31/05/07 deve fazer um update dos dados, e nao esta fazendo isso e sim repetindo os valores e jogando na tabela.

Pois acho eu que o correto seria uma SP, assim ao selecionar os dados da tabela ele pode tanto fazer um update se ja tiver na tabela ou incluir dados novos caso nao tenha.

Alguem pode me ajudar?

Grato
Adriano.


Responder

Gostei + 0

14/06/2007

Emerson Nascimento

se você executar a instrução

select
  id_sal, funcionario, data, descricao, valor, p_d
from
  holerith
where
  (id_sal = :id_sal and funcionario = :funcionario
   and data = :data and descricao = :descricao
   and valor = :valor and p_d = :p_d)


com os parâmetros passados na stored procedure, há resultset?


Responder

Gostei + 0

14/06/2007

Adriano_servitec

Obrigado por responder Emerson, mais ja descobri o erro, estava fazendo o select errado, pois NAO poderiam fazer um select nem de VALORES nem o ID_SAL que no começo estava passando pelo generators, assim nunca ia achar mesmo. :D

O correto deste SP ficou assim
SET TERM ^ ;

CREATE PROCEDURE UPD_INS_HOLERITH (
    id_sal integer,
    funcionario varchar(70),
    data date,
    descricao varchar(60),
    valor numeric(15,2),
    p_d char(1))
as
begin
  if (exists(
        select id_sal, funcionario, data, descricao, valor, p_d
        from holerith where (id_sal = :id_sal and funcionario = :funcionario
        and data = :data and descricao = :descricao)
            )) then
    update holerith
      set id_sal = :id_sal,
          funcionario = :funcionario,
          data = :data,
          descricao = :descricao, 
          valor = :valor,
          p_d = :p_d
       where (id_sal = :id_sal and funcionario = :funcionario
       and data = :data and descricao = :descricao);
   else
     insert into holerith (
       id_sal, 
       funcionario,
       data,
       descricao,
       valor,
       p_d)
     values (
       :id_sal,
       :funcionario,
       :data,
       :descricao,
       :valor,
       :p_d);
end^

SET TERM ; ^

GRANT SELECT,INSERT,UPDATE ON HOLERITH TO PROCEDURE UPD_INS_HOLERITH;

GRANT EXECUTE ON PROCEDURE UPD_INS_HOLERITH TO SYSDBA;


Agora esta funcionando corretamente, bom assim espero, pelo menos nos testes que fiz aqui.

:D

Valeu
Obrigado amigo.


Responder

Gostei + 0

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

Aceitar