Problema para gerar um exception em uma trigger?
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
O que esta errado nesta trigger?
Queria fazer uma unique mais nao estou conseguindo
Fiz assim a unique
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
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
Curtidas 0
Respostas
Adriano_servitec
13/06/2007
Alias, estou mesmo querendo um select + ou - assim
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
E consegui ativar esta query, mais preciso que seja feito diretamente na unit e nao na propriedade SQL do Query.
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.
GOSTEI 0
Emerson Nascimento
13/06/2007
Queria fazer uma unique mais nao estou conseguindo
Fiz assim a unique
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
alter table FOLHA add constraint UNQ1_FOLHA unique (ID_SAL,FUNCIONARIO,DATA,DESCRICAO,VALOR,P_D)
Você não consegue criar a trigger porque já há valores duplicados na tabela. Exclua as duplicidades e tente criar a unique novamente.
GOSTEI 0
Adriano_servitec
13/06/2007
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.
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.
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.
GOSTEI 0
Adriano_servitec
13/06/2007
Pessoal, descobri o erro
Olhem como estava antes
Olhem o correto
Erro no script do SQL :oops:
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:
GOSTEI 0
Adriano_servitec
13/06/2007
Nao deu certo nao, continua repetindo os valores, ai tentei usar uma SP assim:
Mais ao passar a SP pelo componente StoredProc, verifiquei na tabela e nada, continua repetindo os dados.
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.
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.
GOSTEI 0
Emerson Nascimento
13/06/2007
se você executar a instrução
com os parâmetros passados na stored procedure, há resultset?
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?
GOSTEI 0
Adriano_servitec
13/06/2007
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
Agora esta funcionando corretamente, bom assim espero, pelo menos nos testes que fiz aqui.
:D
Valeu
Obrigado amigo.
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.
GOSTEI 0