none
Criando um Trigger RRS feed

  • Pergunta

  • Estou tentando criar um Trigger para armazenar na TABELA1 as alterações feitas na tabelas2

    A tabela2 tera os seguintes campos: (idUsuario, campoAlterado, conteudoAnterior, conteudoAtual)

    Assim sendo preciso ler as tabelas INSERTED e DELETED no meu trigger AFTER UPDATE.

    Estou tentando o seguinte :

    CREATE TRIGGER TR_UPDATE

    ON TABELA2

    AFTER UPDATE

    AS

    BEGIN

    INSERT INTO TABELA1 ( USUARIO, CAMPO, ANTERIOR, ATUAL)

    VALUES (USU.DELETED, CAMPO.DELETED, CONTEUDO.DELETED, CONTEUDO.INSERTED)

    END

    Esta é uma versão resumida do que preciso fazer, pois preciso saber se dentro de um trigger tenho como saber qual campo da tabela está sendo alterado ou terei que comparar todos os campos da tabela DELETED com a INSERTED pra descobrir isso.

    Antecipadamente agradeço,

    Maurício

    quinta-feira, 14 de junho de 2012 13:41

Respostas

  • Maurício,

    É possível testar a atualização da coluna com a função UPDATE(), sem a necessidade de fazer a comparação entre INSERTED e DELETED.

    Veja este meu exemplo:

    create table pedido(id_pedido int identity(1,1), id_produto int, data_pedido datetime)
    go
    
    insert into pedido(id_produto, data_pedido) select 1, GETDATE() + 230
    insert into pedido(id_produto, data_pedido) select 1, GETDATE() + 130
    insert into pedido(id_produto, data_pedido) select 2, GETDATE() + 230
    insert into pedido(id_produto, data_pedido) select 2, GETDATE() + 430
    
    create table atlz_pedido_log(id_pedido int, id_produto_ant int, data_pedido_ant datetime, id_produto_dep int, data_pedido_dep datetime)
    go
    
    CREATE trigger ATLZ_PEDIDO on PEDIDO
    AFTER UPDATE
    as
    BEGIN
    if update(data_pedido)
    begin
    insert into atlz_pedido_log
    select i.id_pedido, i.id_produto, i.data_pedido, d.id_produto, d.data_pedido 
    from deleted d join inserted i on i.id_pedido = d.id_pedido
    end
    end
    go
    
    update pedido set data_pedido = dateadd(d, 1, data_pedido) where id_pedido = 2
    select * from atlz_pedido_log
    
    update pedido set id_produto = id_produto + 1 where id_pedido = 3
    select * from atlz_pedido_log
    
    drop table pedido
    drop table atlz_pedido_log

    Dependendo do uso a ser feito dessa informação, você poderia dar uma olhada no Change Data Capture.

    http://msdn.microsoft.com/pt-br/library/cc645937(v=sql.100).aspx

    http://www.mssqltips.com/sqlservertip/1474/using-change-data-capture-cdc-in-sql-server-2008/


    Antero Marques



    sábado, 16 de junho de 2012 04:01

Todas as Respostas

  • Mauricio,

    confesso que nunca fiz um gatilho para pegar qual campo foi alterado. Mas achei algo que com certeza vai servir pra você:

    http://beyondrelational.com/modules/2/blogs/71/posts/11988/how-to-find-the-right-columns-updated.aspx

    Boa Sorte !



    Antero Marques


    quinta-feira, 14 de junho de 2012 14:39
  • Obrigado, Antero.

    Acho que vai resolver.

    Maurício

    quinta-feira, 14 de junho de 2012 15:31
  • Caro Antero,

    Infelizmente a rotina do link acima não funcionou, e como não sou experiente com SQL Server ficou dificil saber o que está errado, vc teria alguma dica de literatura onde posso aprender sobre triggers

    Grato,

    Maurício

    sexta-feira, 15 de junho de 2012 23:44
  • Maurício,

    É possível testar a atualização da coluna com a função UPDATE(), sem a necessidade de fazer a comparação entre INSERTED e DELETED.

    Veja este meu exemplo:

    create table pedido(id_pedido int identity(1,1), id_produto int, data_pedido datetime)
    go
    
    insert into pedido(id_produto, data_pedido) select 1, GETDATE() + 230
    insert into pedido(id_produto, data_pedido) select 1, GETDATE() + 130
    insert into pedido(id_produto, data_pedido) select 2, GETDATE() + 230
    insert into pedido(id_produto, data_pedido) select 2, GETDATE() + 430
    
    create table atlz_pedido_log(id_pedido int, id_produto_ant int, data_pedido_ant datetime, id_produto_dep int, data_pedido_dep datetime)
    go
    
    CREATE trigger ATLZ_PEDIDO on PEDIDO
    AFTER UPDATE
    as
    BEGIN
    if update(data_pedido)
    begin
    insert into atlz_pedido_log
    select i.id_pedido, i.id_produto, i.data_pedido, d.id_produto, d.data_pedido 
    from deleted d join inserted i on i.id_pedido = d.id_pedido
    end
    end
    go
    
    update pedido set data_pedido = dateadd(d, 1, data_pedido) where id_pedido = 2
    select * from atlz_pedido_log
    
    update pedido set id_produto = id_produto + 1 where id_pedido = 3
    select * from atlz_pedido_log
    
    drop table pedido
    drop table atlz_pedido_log

    Dependendo do uso a ser feito dessa informação, você poderia dar uma olhada no Change Data Capture.

    http://msdn.microsoft.com/pt-br/library/cc645937(v=sql.100).aspx

    http://www.mssqltips.com/sqlservertip/1474/using-change-data-capture-cdc-in-sql-server-2008/


    Antero Marques



    sábado, 16 de junho de 2012 04:01
  • Obrigado mais uma vez Antero,

    O que preciso fazer é um Trigger que existirá para todas as tabelas do DB para criar uma tabela de Log, contendo todas as inserções, alterações e deleções feitas pelos usuário no banco de dados, sabe como é, filho feio não tem pai, e preciso me proteger.

    Criei o Trigger mas está dando o seguinte erro quando tento fazer uma alteração em 1 registro na tabela: O(s) valor(es) da linha atualizado(s) ou excluido(s) não tornan a linha exclusiva ou alteram várias linhas (2 linhas)

    Maurício Bogossian

    sábado, 16 de junho de 2012 18:21
  • Para algo desse porte, te aconselho fortemente a ver a possibilidade de usar o CHANGE DATA CAPTURE.

    Antero Marques

    terça-feira, 19 de junho de 2012 12:18