Fórum Como usar Trigger? #57630

10/01/2007

0

Pessoal ainda nao testei, estou querendo aprender a usar as trigger, entao fiz essa trigger

SET SQL DIALECT 3;

SET NAMES ISO8859_1;


SET TERM ^ ;


CREATE TRIGGER RESTRICAOVALORTBCONTA FOR TBCONTA
ACTIVE BEFORE INSERT POSITION 0
AS
begin
  /* Trigger Para nao ficar valor null*/
  if (Exists(Select * from tbconta where valor = ´´) ) then
  Exception RESTRICAO ´O campo valor nao pode ficar em branco´;
end
^


SET TERM ; ^


A ideia eh para criar uma restriçao aonde nao pode incluir valores nulos no campo valor da tabela, a restricao ja criei no [b:f22e41ee56]Exception[/b:f22e41ee56] do IBExpert, entao gostaria de saber se esta certo essa Trigger?

Agradeço a opniao de todos.
Adriano.

[b:f22e41ee56][color=blue:f22e41ee56]E tambem se puderem me explicar, se eh melhor usar trigger, em vez de usar codigos dentro da unit do delphi! Ou seja eu posso muito bem fazer um codigo de restriçao no evento onexit do componente, mais gostaria da opnião do pessoal, se eh mais vantajoso usar na trigger ou no programa mesmo.[/color:f22e41ee56][/b:f22e41ee56]

Abçs;


Adriano_servitec

Adriano_servitec

Responder

Posts

10/01/2007

Sremulador

primeiramente crei isto

CREATE EXCEPTION RESTRICAO´CAMPO NÃO PODE SER NULO´;


depois ajuste o gatilho

CREATE TRIGGER RESTRICAOVALORTBCONTA FOR TBCONTA 
ACTIVE BEFORE INSERT POSITION 0 
AS 
begin 
  /* Trigger Para nao ficar valor null*/ 
  if (Exists(Select * from tbconta where valor is null ) then 
      Exception RESTRICAO; 
end 


os gatilhos são como ações assim como ocorre no delphi, tipo onclick, onexit, assim vai, neste caso são antes de inserir, depois, antes de exluir depois, antes de alterar e depois


Responder

Gostei + 0

10/01/2007

Adriano_servitec

Obrigado por me ajudar [b:9c0cbb9b8f]sremulador[/b:9c0cbb9b8f]

O mesmo se aplica para esta ação tambem sremulador?
ALTER TRIGGER UNIQSEQCONTA
ACTIVE BEFORE INSERT POSITION 0
AS
begin
 if ( Exists(Select * from tbconta WHERE sequencia = NEW.sequencia ) )
then
  Exception RESTRICAO ´Campo Matrícula Já Existe!´;
end



Responder

Gostei + 0

10/01/2007

Sremulador

Amigo os exceptions voc^?e cria apenas uma vez, e utiliza apenas o nome

ALTER TRIGGER UNIQSEQCONTA 
ACTIVE BEFORE INSERT POSITION 0 
AS 
begin 
 if ( Exists(Select * from tbconta WHERE sequencia = NEW.sequencia ) ) 
then 
  Exception RESTRICAO; 
end


No caso de seu select não haveria ´Acho´ do * já que e uma comparação sem pegar resultados para um terceiro tratamento, assim ficará mais rapido a ação...


Responder

Gostei + 0

10/01/2007

Adriano_servitec

Amigo os exceptions voc^?e cria apenas uma vez, e utiliza apenas o nome
Sim eu criei somente uma vez
CREATE EXCEPTION RESTRICAO ´´;
Mais deixei ele vazio para preencher conforme a mensagem que desejo que apareça no form.

No caso de seu select não haveria ´Acho´ do * já que e uma comparação sem pegar resultados para um terceiro tratamento, assim ficará mais rapido a ação...
Entao em vez de usar *(curinga para todos) o certo seria somente o campo que faz a restrição?

Valeu amigo.


Responder

Gostei + 0

10/01/2007

Emerson Nascimento

creio que o correto seria:
CREATE TRIGGER RESTRICAOVALORTBCONTA FOR TBCONTA
ACTIVE BEFORE INSERT POSITION 0
AS
begin
  /* Trigger Para nao ficar valor null*/
  if (NEW.VALOR IS NULL) then
    Exception RESTRICAO;
end



Responder

Gostei + 0

10/01/2007

Adriano_servitec

creio que o correto seria:
CREATE TRIGGER RESTRICAOVALORTBCONTA FOR TBCONTA
ACTIVE BEFORE INSERT POSITION 0
AS
begin
  /* Trigger Para nao ficar valor null*/
  if (NEW.VALOR IS NULL) then
    Exception RESTRICAO;
end
Entao nao preciso fazer um select? eh soh usar assim como vc postou amigo? e esse outro que eu fiz para ser um unique, tambem devo modificar?
AS
begin
 if ( Exists(Select * from tbconta WHERE sequencia = NEW.sequencia ) )
then
  Exception RESTRICAO;
end
Pois aqui nesse caso eu usei o exists para verificar se ja tem esse campo cadastrado no banco depois mandar a mensagem.


Responder

Gostei + 0

10/01/2007

Sremulador

Realmente nãp prestei atenção, se for na mesma tabela não, mas se for em outra tabela você teria que fazer o select...


Responder

Gostei + 0

10/01/2007

Sremulador

Mas outra forma de fazer isso e setando o campo para não aceitar valor nulo..., a diferença e que não vai exibir a mensagem personalizada...


Responder

Gostei + 0

10/01/2007

Adriano_servitec

Obrigado pessoal, agora ja estou entendendo.

Mais uma pergunta essas triger ela dispara somente na hora em que vou gravar no banco ou tem como disparar antes? Como faço no evento onexit dentro do delphi.

Ainda mais uma pergunta: Tenho uma tabela com campos assim

tabmovimento
sequencia
conta
descricao
valor

e outra tabdebido(tabela filha)
sequencia (FK) (Refernecia com a tabela tabmovimento)
conta_D
descricao
valor

E na hora em que eu for gravar no form vai gravar na tabmovimento o que eu digitar no form, a pergunta seria como posso gravar tambem os mesmos dados na tabela (filha)? Preciso ao mesmo tempo fazer um codigo para as duas tabelas tipo assim

insert into tabmovimento
....
parambyname(´campos´).AsString:=editConta;
execsql

insert into tabdebito
...
parambyname(´campos´).AsString:=editConta;
execSQL

Ou tem como fazer somente em uma tabela e a outra ja receber o resultado?


Responder

Gostei + 0

10/01/2007

Sremulador

Mais uma pergunta essas triger ela dispara somente na hora em que vou gravar no banco ou tem como disparar antes? Como faço no evento onexit dentro do delphi.


Tem a opção Antes e Depois

Belfore Alfter

tabmovimento sequencia conta descricao valor e outra tabdebido(tabela filha) sequencia (FK) (Refernecia com a tabela tabmovimento) conta_D descricao valor E na hora em que eu for gravar no form vai gravar na tabmovimento o que eu digitar no form, a pergunta seria como posso gravar tambem os mesmos dados na tabela (filha)? Preciso ao mesmo tempo fazer um codigo para as duas tabelas tipo assim insert into tabmovimento .... parambyname(´campos´).AsString:=editConta; execsql insert into tabdebito ... parambyname(´campos´).AsString:=editConta; execSQL Ou tem como fazer somente em uma tabela e a outra ja receber o resultado?


Diretamente no db somente /se um usuário estiver por vez, mas desconhece...


Responder

Gostei + 0

10/01/2007

Adriano_servitec

Entao o melhro eh criar um Stored Procedure + ou - assim:

Supondo que a estrutura da tabela fosse:

Mestre
----------------
Codigo - Integer
Descricao - Varchar(50)
Data - Date

Detalhe
----------------
Cod_Mestre - Integer
Cod_Produto - Integer
Quantidade - Integer

Set term ^ ;
create procedure GravaDados(
       Cod_Mestre Integer,
       Desc_Mestre varchar(50),
       Data_Mestre Date,
       Cod_Produto Integer,
       Quantidade Integer
)
as
begin
  if ( not exists(select codigo from Mestre where codigo = :Cod_Mestre) )then
    Insert into Mestre Values ( Cod_Mestre, Desc_Mestre, Data_Mestre );
  Insert into Detalhe Values (Cod_Mestre, Cod_Produto, Quantidade );
end
^
Set Term ; ^ 



Responder

Gostei + 0

11/01/2007

Adriano_servitec

Bom a Stored Procedure jah esta criada
(Espero que esteja correta) :D
SET TERM ^ ;

CREATE PROCEDURE GRAVADADOS (
    SEQUENCIA INTEGER,
    CONTA VARCHAR(15),
    HISTORICO VARCHAR(100),
    VALOR NUMERIC(15,2),
    CONTAD VARCHAR(15))
AS
begin
if ( not exists(select * from tbconta where sequencia = :sequencia) )
  then
   Insert Into tbconta (sequencia, conta, historico, valor) Values (:sequencia, :conta, :historico, :valor);

   Insert into debito (sequencia, contad, historico, valor) Values ( :sequencia, :contad, :historico, :valor );
Suspend;
end^

SET TERM ; ^

GRANT SELECT,INSERT ON TBCONTA TO PROCEDURE GRAVADADOS;

GRANT INSERT ON DEBITO TO PROCEDURE GRAVADADOS;

GRANT EXECUTE ON PROCEDURE GRAVADADOS TO SYSDBA;

Agora entao se eu for usar query ou IBStoredProc terei que passar os parametros da SP que eu criei?

Tipo assim:
[b:8c9475a6ae]select * form GRAVADADOS (:SEQUENCIA, :CONTA, :HISTORICO, :VALOR, :CONTAD)[/b:8c9475a6ae]assim da erro [color=red:8c9475a6ae]procedure gravadados does not return any values delphi[/color:8c9475a6ae]

Usando um IBStoredProcedure da o sequinte erro: [color=red:8c9475a6ae]use execproc for procedure use tquery for select procedure delphi[/color:8c9475a6ae] Neste caso eu apontei a propriedade StoredProcName para GRAVADADOS , e apareçe os paramentro da propriedade parametes assim:
0-sequencia
1-conta
2-historico
3-valor
4-contad

O que esta errado pq nao consigo ativar nenhum dois dois modos?

Outra coisa
IBStoredProc deve ser usado para Procedures executáveis, para SELECT procedures use um IBQuery.
No caso essa Stored Procedure que eu criei, se aplica em qual caso segundo esse quote acima?

Pq o que eu quero que essa Stored procedure faça eh incluir dois lançamentos (alias serah 3 lançamentos de uma soh vez, ou seja vai incluir na tabela movimento, debito e credito de uma soh vez).

Grato a ajuda de todos.
Adriano.


Responder

Gostei + 0

11/01/2007

Emerson Nascimento

vc deve usar, numa query:
EXECUTE PROCEDURE GRAVADADOS (:SEQUENCIA, :CONTA, :HISTORICO, :VALOR, :CONTAD)
e chamar o método Execute (ou similar). nesse caso não se usa open.

no IBStoredProcedure você deve apenas preencher os parâmetros e executá-la. outra coisa: não sei se tem influência no erro, mas, como sua SP não retorna dados, o [i:ceaaea2395]Suspend[/i:ceaaea2395] é desnecessário.


Responder

Gostei + 0

11/01/2007

Emerson Nascimento

outra coisa: creio que falta um begin/end na SP:
CREATE PROCEDURE GRAVADADOS ( 
    SEQUENCIA INTEGER, 
    CONTA VARCHAR(15), 
    HISTORICO VARCHAR(100), 
    VALOR NUMERIC(15,2), 
    CONTAD VARCHAR(15)) 
AS 
begin 
  if ( not exists(select sequencia from tbconta where sequencia = :sequencia) ) then
  begin
    Insert Into tbconta (sequencia, conta, historico, valor)
      values (:sequencia, :conta, :historico, :valor); 

    Insert into debito (sequencia, contad, historico, valor)
      values ( :sequencia, :contad, :historico, :valor ); 
  end;
--  Suspend; 
end^
obs.: na verdade somente ponha o begin/end se as duas instruções insert forem casadas (executadas juntas)


Responder

Gostei + 0

11/01/2007

Adriano_servitec

vc deve usar, numa query: EXECUTE PROCEDURE GRAVADADOS (:SEQUENCIA, :CONTA, :HISTORICO, :VALOR, :CONTAD) e chamar o método Execute (ou similar). nesse caso não se usa open. no IBStoredProcedure você deve apenas preencher os parâmetros e executá-la. outra coisa: não sei se tem influência no erro, mas, como sua SP não retorna dados, o [i:eab27f7f14]Suspend[/i:eab27f7f14] é desnecessário.


Soh mais uma pergunta Emerson, eu escrevo:
[b:eab27f7f14]EXECUTE PROCEDURE GRAVADADOS (:SEQUENCIA, :CONTA, :HISTORICO, :VALOR, :CONTAD)[/b:eab27f7f14] dentro da propriedade SQL? ou faço algo tipo assim num button que vou usar para incluir os dados:
with dm.QuerySProc do
begin
   close;
   SQL.clear;
   sql.add(´EXECUTE PROCEDURE GRAVADADOS (:SEQUENCIA, :CONTA,    :HISTORICO, :VALOR, :CONTAD)´);
ExecSQL


obs.: na verdade somente ponha o begin/end se as duas instruções insert forem casadas (executadas juntas)
Sim elas sao casadas como vc disse ou seja vao fazer o mesmo processo de gravaçao de dados, inclusive vai ter mais outra tabela chamada credito que vai estar casada tambem com a tabela movimento(tabela mestre)

[b:eab27f7f14]Obs:A StoredProcedure eu vou arrumar cfe. vc postou.[/b:eab27f7f14]

Desculpe por postar essas perguntas, mais realmente ainda nao sei usar Stored Procedure.

[color=blue:eab27f7f14]Sobre os compoentes IBStoredProc e IBQuery se possivel for prefiro usar o IBQuery.[/color:eab27f7f14]

Obrigado amigo.


Responder

Gostei + 0

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

Aceitar