Declarando Cursores (SQL) - Carnette Socorro!!!
20/05/2003
0
Em especial pro mano carnette!
meu problema é:
tenho que fazer um log de uma tabela no sql 6.5, dai fiz uma trigger que faz quase tudo direitinho. Ela ve se a tabela inserted e a deleted contém registros e em caso positivo ela entende que trata-se de uma alteração e copia o conteudo da deleted pra uma tabela de log que tem a estrutura igual a original mais os campos quem, onde e quando, os quais ela poe o nome do usuario, estação de trabalho e data/hora (Suser_Name(),Host_Name(),GetDate()) e depois faz o mesmo pra inserted, dai na auditoria da pra ver o que foi alterado comparando um registro com o próximo. Isso funciona muito bem, só pega quando eu faço uma alteração em bloco, nesse caso, a tabela de log fica com todos os registros deletados e depois todos os registros inseridos (o ideal seria alternados deletado e inserido).
Solução: preciso criar um cursor só que eu NÃO SEI FAZER ISSO!
Por favor, preciso de um exemplo de cursor com um ´while not eof´ pra eu poder, no caso, inserir na tebela de log um registro de cada vez
Flavio Sanches
Posts
20/05/2003
Flavio Sanches
drop trigger dbo.tr_LogFinanceiro_imob
GO
CREATE TRIGGER tr_LogFinanceiro_imob ON dbo.Financeiro_imob
FOR INSERT,UPDATE,DELETE
AS
/* Cria o trigger para log das operacoes dos usuarios
Na Tabela Financeiro_Imob
AUTOR : FLÁVIO SANCHES
DATA : 31/01/2003
*/
-- Testa se Tem algum registro na tabela Inserted
If exists(Select inscricao_imob from Inserted)
Begin
-- Testa se Tem algum registro na tabela Deleted
If exists(Select inscricao_imob from deleted)
begin
-- se tem registro em ambas as tabelas entao a operacao e alteracao
-- insere no log o registro antes da operacao
Insert Into lg_Financ_imob (
Usuario ,estacao ,Dia_Hora ,
Operacao ,Inscricao_imob ,chave_ident ,
Ano_Divida ,cod_Divida ,Sub_Divida ,
Cod_Tipo_Moeda ,Parcela ,Vencimento ,
Valor ,Cod_Situacao_Divida ,Num_Termo_Origem ,
Ano_Termo_Origem ,Num_Termo_Destino ,Ano_Termo_Destino ,
TEM_COMPOSICAO ,Qtde_Parc_Agrup )
select Suser_Name() ,Host_Name() ,GetDate() ,
´A´ ,Inscricao_imob ,chave_ident ,
Ano_Divida ,cod_Divida ,Sub_Divida ,
Cod_Tipo_Moeda ,Parcela ,Vencimento ,
Valor ,Cod_Situacao_Divida ,Num_Termo_Origem ,
Ano_Termo_Origem ,Num_Termo_Destino ,Ano_Termo_Destino ,
TEM_COMPOSICAO ,Qtde_Parc_Agrup
from deleted
-- Insere na Tabela o registro Depois da operacao
Insert Into lg_Financ_imob (
Usuario ,estacao ,Dia_Hora ,
Operacao ,Inscricao_imob ,chave_ident ,
Ano_Divida ,cod_Divida ,Sub_Divida ,
Cod_Tipo_Moeda ,Parcela ,Vencimento ,
Valor ,Cod_Situacao_Divida ,Num_Termo_Origem ,
Ano_Termo_Origem ,Num_Termo_Destino ,Ano_Termo_Destino ,
TEM_COMPOSICAO ,Qtde_Parc_Agrup )
select Suser_Name() ,Host_Name() ,GetDate() ,
´A´ ,Inscricao_imob ,chave_ident ,
Ano_Divida ,cod_Divida ,Sub_Divida ,
Cod_Tipo_Moeda ,Parcela ,Vencimento ,
Valor ,Cod_Situacao_Divida ,Num_Termo_Origem ,
Ano_Termo_Origem ,Num_Termo_Destino ,Ano_Termo_Destino ,
TEM_COMPOSICAO ,Qtde_Parc_Agrup
from Inserted
End
Else
Begin
-- Se nao tem registro na tabela deleted entao a operacao e de inclusao
Insert Into lg_Financ_imob (
Usuario ,estacao ,Dia_Hora ,
Operacao ,Inscricao_imob ,chave_ident ,
Ano_Divida ,cod_Divida ,Sub_Divida ,
Cod_Tipo_Moeda ,Parcela ,Vencimento ,
Valor ,Cod_Situacao_Divida ,Num_Termo_Origem ,
Ano_Termo_Origem ,Num_Termo_Destino ,Ano_Termo_Destino ,
TEM_COMPOSICAO ,Qtde_Parc_Agrup )
select Suser_Name() ,Host_Name() ,GetDate() ,
´I´ ,Inscricao_imob ,chave_ident ,
Ano_Divida ,cod_Divida ,Sub_Divida ,
Cod_Tipo_Moeda ,Parcela ,Vencimento ,
Valor ,Cod_Situacao_Divida ,Num_Termo_Origem ,
Ano_Termo_Origem ,Num_Termo_Destino ,Ano_Termo_Destino ,
TEM_COMPOSICAO ,Qtde_Parc_Agrup
from inserted
End
End
Else
Begin
-- Se nao tem registro na tabela Inserted entao a operacao e de exclusao
-- Insere no log o registro apagado
Insert Into lg_Financ_imob (
Usuario ,estacao ,Dia_Hora ,
Operacao ,Inscricao_imob ,chave_ident ,
Ano_Divida ,cod_Divida ,Sub_Divida ,
Cod_Tipo_Moeda ,Parcela ,Vencimento ,
Valor ,Cod_Situacao_Divida ,Num_Termo_Origem ,
Ano_Termo_Origem ,Num_Termo_Destino ,Ano_Termo_Destino ,
TEM_COMPOSICAO ,Qtde_Parc_Agrup )
select Suser_Name() ,Host_Name() ,GetDate() ,
´E´ ,Inscricao_imob ,chave_ident ,
Ano_Divida ,cod_Divida ,Sub_Divida ,
Cod_Tipo_Moeda ,Parcela ,Vencimento ,
Valor ,Cod_Situacao_Divida ,Num_Termo_Origem ,
Ano_Termo_Origem ,Num_Termo_Destino ,Ano_Termo_Destino ,
TEM_COMPOSICAO ,Qtde_Parc_Agrup
from deleted
End
GO
20/05/2003
Cac2000
create trigger tr_grava_log on tabela1
for insert, update, delete
as
declare @campo1_ins int, @campo2_ins int, @campo3_ins int,
@campo1_del int, @campo2_del int, @campo3_del int
declare cur_ins cursor for
select campo1, campo2, campo3
from inserted
declare cur_del cursor for
select campo1, campo2, campo3
from deleted
fetch cur_ins into @campo1_ins, @campo2_ins, @campo3_ins
fetch cur_del into @campo1_del, @campo2_del, @campo3_del
while @@fetch_status = 0 -- mesmo que WHILE NOT EOF
begin
-- aqui dentro vc grava nas suas tabelas de log, usando as variaveis(@)
fetch cur_ins into @campo1_ins, @campo2_ins, @campo3_ins
fetch cur_del into @campo1_del, @campo2_del, @campo3_del
end
end
21/05/2003
Flavio Sanches
Desculpe se pareci preferir a resposta do carnette, mas é que temos que reconhecer que o cara é bom pra caraca.
Só mais uma dúvida...
É claro que eu procurei tb em livros por aqui e lá tinha um exemplo parecido com o seu (cac2000), só que ele usava @@fetch_next ou algo parecido e vc usa só @@fetch. Qual seria a diferença? Pelo que eu entendi o fetch next lê o registro atual ponteirado e move o ponteiro automaricamente pro próximo registro. Não seria mais apropriado???
De qq forma, Valeu!!!
21/05/2003
Aroldo Zanela
Desculpe se pareci preferir a resposta do carnette, mas é que temos que reconhecer que o cara é bom pra caraca.
Só mais uma dúvida...
É claro que eu procurei tb em livros por aqui e lá tinha um exemplo parecido com o seu (cac2000), só que ele usava @@fetch_next ou algo parecido e vc usa só @@fetch. Qual seria a diferença? Pelo que eu entendi o fetch next lê o registro atual ponteirado e move o ponteiro automaricamente pro próximo registro. Não seria mais apropriado???
De qq forma, Valeu!!![/quote:8b3e265ac1]
A instrução FETCH busca uma linha na direção especificada que pode ser NEXT, PRIOR, FIRST, LAST, ABSOLUTE n ou RELATIVE n. A direção default é NEXT. Quando bem sucedida retorna 0 em @@fetch_status.
Peguei um gancho com o exemplo do nosso colega cac2000 e adicionei algumas instruções para não ocorrer erros, no caso de você se esquecer de abrir, fechar e desalocar os cursores:
create trigger tr_grava_log on tabela1 for insert, delete as declare @campo1_ins int, @campo2_ins int, @campo3_ins int, @campo1_del int, @campo2_del int, @campo3_del int declare cur_ins cursor for select campo1, campo2, campo3 from inserted declare cur_del cursor for select campo1, campo2, campo3 from deleted /* Abrir os cursores */ open cur_ins open cur_del while @@fetch_status = 0 /* Enquanto não percorrer os registros de ambas as tabelas */ begin fetch next from cur_ins into @campo1_ins, @campo2_ins, @campo3_ins Insert into TabelaLOG values(@campo1_ins, @campo2_ins, @campo3_ins) fetch next from cur_del into @campo1_del, @campo2_del, @campo3_del Insert into TabelaLOG values(@campo1_del, @campo2_del, @campo3_del) end /* Fechar cursores */ close cur_ins close cur_del /* Remover a alocação dos cursoses */ deallocate cur_ins deallocate cur_del end
22/05/2003
Flavio Sanches
Zanela...Cac2000...Etc
E o meu camarada carnette que sumiu...
Consegui graças a ajuda de vcs.
abraços
22/05/2003
Carnette
Zanela...Cac2000...Etc
E o meu camarada carnette que sumiu...
Consegui graças a ajuda de vcs.
abraços[/quote:7759348a8e]
O Camarada carnette sumiu...Porque ficou pensando pensando pensando.....e só pensando.....Mas, nada melhor do que ter companheiros competentes aqui no forum..que em vez de ficarem só pensando....respondem as questões......tbm agradeço as respostas dos companheiros acima e podem ter certeza que as dicas já estão guardadas....
22/05/2003
Flavio Sanches
O bagulho ficou legal,
Só que funciona de vez em quando...
Ou seja, no update ele faz umas e não faz outras vezes.
alguém tem alguma idéia de como resolvere isso???
tenho um livro aqui que diz que é possível na mesma trigger, separar os eventos insert,delete e update, será que isso resolve???
minha trigger está assim:
if exists (select * from sysobjects where id = object_id(´dbo.tr_LogFinanceiro_imob´) and sysstat & 0xf = 8)
drop trigger dbo.tr_LogFinanceiro_imob
GO
CREATE TRIGGER tr_LogFinanceiro_imob ON dbo.Financeiro_imob
FOR INSERT,UPDATE,DELETE
AS
/* Cria o trigger para log das operacoes dos usuarios
Na Tabela Financeiro_imob
AUTOR : FLÁVIO SANCHES
DATA : 21/05/2003
*/
-- Declara as variaveis dos campos da tabela onde o trigger atua
Declare
@Inscricao_imob char(6) ,
@chave_ident char(3) ,
@Ano_Divida char(4) ,
@Cod_Divida char(2) ,
@Sub_Divida char(2) ,
@Cod_Tipo_Moeda char(2) ,
@Parcela char(2) ,
@Vencimento DateTime,
@Valor float ,
@Cod_Situacao_Divida char(2) ,
@Num_Termo_Origem char(6) ,
@Ano_Termo_Origem char(4) ,
@Num_Termo_Destino char(6) ,
@Ano_Termo_Destino char(4) ,
@Qtde_Parc_Agrup char(2) ,
@Tem_Composicao char(1)
-- Testa se Tem algum registro na tabela Inserted
If exists(Select inscricao from Inserted)
Begin
-- Testa se Tem algum registro na tabela Deleted
If exists(Select inscricao from deleted)
begin
-- se tem registro em ambas as tabelas entao a operacao e alteracao
-- insere no log o registro antes da operacao
Declare cur_ins Cursor For
Select
Inscricao_imob ,Chave_ident ,Ano_Divida ,Cod_Divida ,
Sub_Divida ,Cod_Tipo_Moeda ,Parcela ,Vencimento ,
Valor ,Cod_Situacao_Divida ,Num_Termo_Origem ,Ano_Termo_Origem ,
Num_Termo_Destino ,Ano_Termo_Destino ,Qtde_Parc_Agrup ,Tem_Composicao
from Inserted
Open cur_ins
Declare cur_del Cursor For
Select
Inscricao_imob ,Chave_ident ,Ano_Divida ,Cod_Divida ,
Sub_Divida ,Cod_Tipo_Moeda ,Parcela ,Vencimento ,
Valor ,Cod_Situacao_Divida ,Num_Termo_Origem ,Ano_Termo_Origem ,
Num_Termo_Destino ,Ano_Termo_Destino ,Qtde_Parc_Agrup ,Tem_Composicao
from deleted
Open cur_del
While (@@Fetch_Status <> -1)
Begin
Fetch Next From cur_del
Into
@Inscricao_imob ,@Chave_ident ,@Ano_Divida ,@Cod_Divida ,
@Sub_Divida ,@Cod_Tipo_Moeda ,@Parcela ,@Vencimento ,
@Valor ,@Cod_Situacao_Divida ,@Num_Termo_Origem ,@Ano_Termo_Origem ,
@Num_Termo_Destino ,@Ano_Termo_Destino ,@Qtde_Parc_Agrup ,@Tem_Composicao
Insert Into Lg_Financ_imob (
Usuario ,estacao ,Dia_Hora ,Operacao ,
Inscricao_imob ,Chave_ident ,Ano_Divida ,Cod_Divida ,
Sub_Divida ,Cod_Tipo_Moeda ,Parcela ,Vencimento ,
Valor ,Cod_Situacao_Divida ,Num_Termo_Origem ,Ano_Termo_Origem ,
Num_Termo_Destino ,Ano_Termo_Destino ,Qtde_Parc_Agrup ,Tem_Composicao
)Values(
Suser_Name() ,Host_Name() ,GetDate() ,´A´ ,
@Inscricao_imob ,@Chave_ident ,@Ano_Divida ,@Cod_Divida ,
@Sub_Divida ,@Cod_Tipo_Moeda ,@Parcela ,@Vencimento ,
@Valor ,@Cod_Situacao_Divida ,@Num_Termo_Origem ,@Ano_Termo_Origem ,
@Num_Termo_Destino ,@Ano_Termo_Destino ,@Qtde_Parc_Agrup ,@Tem_Composicao )
Fetch Next From cur_ins
Into
@Inscricao_imob ,@Chave_ident ,@Ano_Divida ,@Cod_Divida ,
@Sub_Divida ,@Cod_Tipo_Moeda ,@Parcela ,@Vencimento ,
@Valor ,@Cod_Situacao_Divida ,@Num_Termo_Origem ,@Ano_Termo_Origem ,
@Num_Termo_Destino ,@Ano_Termo_Destino ,@Qtde_Parc_Agrup ,@Tem_Composicao
Insert Into Lg_Financ_imob (
Usuario ,estacao ,Dia_Hora ,Operacao ,
Inscricao_imob ,Chave_ident ,Ano_Divida ,Cod_Divida ,
Sub_Divida ,Cod_Tipo_Moeda ,Parcela ,Vencimento ,
Valor ,Cod_Situacao_Divida ,Num_Termo_Origem ,Ano_Termo_Origem ,
Num_Termo_Destino ,Ano_Termo_Destino ,Qtde_Parc_Agrup ,Tem_Composicao
)Values(
Suser_Name() ,Host_Name() ,GetDate() ,´A´ ,
@Inscricao_imob ,@Chave_ident ,@Ano_Divida ,@Cod_Divida ,
@Sub_Divida ,@Cod_Tipo_Moeda ,@Parcela ,@Vencimento ,
@Valor ,@Cod_Situacao_Divida ,@Num_Termo_Origem ,@Ano_Termo_Origem ,
@Num_Termo_Destino ,@Ano_Termo_Destino ,@Qtde_Parc_Agrup ,@Tem_Composicao
)
End
Close cur_del
Deallocate cur_del
Close cur_ins
Deallocate cur_ins
End
Else
Begin
-- Se nao tem registro na tabela deleted entao a operacao e de inclusao
Insert Into lg_Financ_imob (
Usuario ,estacao ,Dia_Hora ,Operacao ,
Inscricao_imob ,Chave_ident ,Ano_Divida ,Cod_Divida ,
Sub_Divida ,Cod_Tipo_Moeda ,Parcela ,Vencimento ,
Valor ,Cod_Situacao_Divida ,Num_Termo_Origem ,Ano_Termo_Origem ,
Num_Termo_Destino ,Ano_Termo_Destino ,Qtde_Parc_Agrup ,Tem_Composicao )
select
Suser_Name() ,Host_Name() ,GetDate() ,´I´ ,
Inscricao_imob ,Chave_ident ,Ano_Divida ,Cod_Divida ,
Sub_Divida ,Cod_Tipo_Moeda ,Parcela ,Vencimento ,
Valor ,Cod_Situacao_Divida ,Num_Termo_Origem ,Ano_Termo_Origem ,
Num_Termo_Destino ,Ano_Termo_Destino ,Qtde_Parc_Agrup ,Tem_Composicao
from inserted
End
End
Else
Begin
-- Se nao tem registro na tabela Inserted entao a operacao e de exclusao
-- Insere no log o registro apagado
Insert Into lg_Financ_imob (
Usuario ,estacao ,Dia_Hora ,Operacao ,
Inscricao_imob ,Chave_ident ,Ano_Divida ,Cod_Divida ,
Sub_Divida ,Cod_Tipo_Moeda ,Parcela ,Vencimento ,
Valor ,Cod_Situacao_Divida ,Num_Termo_Origem ,Ano_Termo_Origem ,
Num_Termo_Destino ,Ano_Termo_Destino ,Qtde_Parc_Agrup ,Tem_Composicao )
select
Suser_Name() ,Host_Name() ,GetDate() ,´I´ ,
Inscricao_imob ,Chave_ident ,Ano_Divida ,Cod_Divida ,
Sub_Divida ,Cod_Tipo_Moeda ,Parcela ,Vencimento ,
Valor ,Cod_Situacao_Divida ,Num_Termo_Origem ,Ano_Termo_Origem ,
Num_Termo_Destino ,Ano_Termo_Destino ,Qtde_Parc_Agrup ,Tem_Composicao
from deleted
End
GO
Clique aqui para fazer login e interagir na Comunidade :)