/ / Como manter uma auditoria / histórico de alterações na tabela - sql-server, tsql, ado.net, triggers

Como manter uma auditoria / histórico de mudanças na tabela - sql-server, tsql, ado.net, triggers

Eu fui solicitado a criar um estilo DataGrid simplesaplicativo para editar uma única tabela de um banco de dados, e isso é bastante fácil. Mas parte da solicitação é criar uma trilha de auditoria das alterações feitas, quem as criou e a data / hora.

Como você pode resolver esse tipo de coisa?

(Eu estarei usando o C # no VS2008, o ADO.NET conectado ao SQL Server 2005, o DataGrid do WPF e Xceed, se fizer alguma diferença.)

Respostas:

11 para resposta № 1

Existem duas maneiras comuns de criar trilhas de auditoria.

  1. Codifique sua camada de acesso a dados.
  2. No próprio banco de dados usando gatilhos.

Há vantagens e desvantagens para ambos. Algumas pessoas preferem uma sobre a outra. Geralmente, é o tipo de aplicativo e o tipo de uso de banco de dados que você pode esperar.

Se você fizer isso na sua camada DA, é praticamentepara você. Você só precisa adicionar código a cada método que salva no banco de dados para também salvar um log das mudanças. Este código de auditoria pode estar em seu código de camada DA, ou mesmo em seus procedimentos armazenados em seu banco de dados, se você estiver usando procs armazenados para tudo. Essencialmente, a premissa é a mesma, sempre que você fizer uma alteração no banco de dados, registre essa alteração.

Se você quiser descer a rota de gatilhos, poderá escrever gatilhos personalizados para cada tabela ou criar um gatilho mais genérico que funcione da mesma forma em várias tabelas. Confira Este artigo em disparadores de auditoria. Isso funciona disparando gatilhos sempre que uma alteração é feita e os gatilhos registram as alterações. Lembre-se que se você deseja auditar instruções SELECT, você não pode usar gatilhos, você terá que fazer isso com a auditoria de proc de código / armazenado. Vale lembrar também que, dependendo do banco de dados, os gatilhos podem não disparar em todas as circunstâncias. Por exemplo, a maioria dos bancos de dados não aciona gatilhos durante as instruções TRUNCATE. Verifique se seus gatilhos são acionados em qualquer caso que você precisa de auditoria.

Alternativamente, você também pode dar uma olhada em usar o corretor de serviços fazer auditoria assíncrona em uma máquina dedicada. Isso é mais complexo e exige um pouco de configuração para ser configurado.

De que maneira você faz isso, você precisa decidiro formato que o log de auditoria levará. Normalmente, você salvaria esse log no banco de dados, mas poderia salvá-lo em um arquivo de log ou em qualquer outro que fosse adequado aos seus requisitos. Você pode usar uma única tabela de auditoria que registra todas as alterações ou pode ter uma tabela de auditoria por tabela principal sendo auditada. Para implementações em grande escala, você pode até considerar colocar as tabelas de auditoria em um banco de dados totalmente separado. Se o seu login em uma tabela, é comum ter um campo "tipo de mudança", que indica se a alteração auditada foi um estilo de inserção, atualização ou exclusão, juntamente com os dados alterados, o usuário que fez a alteração e a data / time a alteração foi feita. Não se esqueça de incluir os dados antigos e novos para as mudanças no estilo de atualização.


8 para resposta № 2

O método mais universal seria criar outrotabela para armazenar versões de registro da primeira tabela. Em seguida, você pode remover todos os dados da tabela principal. Suponha que você precise de versionamento de uma tabela Person (PersonId, Name, Surname):

CREATE TABLE Person ( PersonId INT,    // PK CurrentPersonVersion INT // FK );  CREATE TABLE PersonVersion ( PersonVersionId INT, // PK PersonID // FK Nome VARCHAR, // dados reais Sobrenome VARCHAR, // dados reais  ChangeDate // log de dados ChangeAuthor // registrando dados )

Agora, qualquer alteração requer a inserção de um novo PersonVersion e a atualização do CurrentPersonVersionID.


8 para resposta № 3

Ditto usa gatilhos.

Qualquer pessoa que esteja considerando a exclusão suave deve ler Richard Dingwall's O problema com a exclusão suave.


2 para resposta № 4

A melhor maneira de fazer isso é configurar os acionadores no banco de dados que gravam em tabelas de auditoria.


1 para resposta № 5

Recentemente, fui confrontado com um requisito para auditaralgumas tabelas e optei por usar gatilhos. Como outros, eu só queria ver as entradas na tabela de auditoria para os campos que realmente haviam mudado, no entanto, ao atualizar as tabelas, o aplicativo estava atualizando todos os campos da linha se eles tinham "alterado ou não, portanto, verificando se campos foram atualizados ou não me serviram de nada - todos eles tinham!

O que eu queria, portanto, era um método deVerificando o valor real em cada campo para ver se ele foi alterado ou não e apenas gravá-lo na tabela de auditoria, se houver. Tendo sido incapaz de encontrar qualquer solução para este enigma em qualquer lugar, eu criei o meu próprio, da seguinte forma:

CREATE TRIGGER [dbo].[MyTable_CREATE_AUDIT]
ON [dbo].[MyTable]
AFTER UPDATE

AS

INSERT INTO MyTable_Audit
(ItemID,LastModifiedBy,LastModifiedDate,field1,field2,field3,
field4,field5,AuditDate)
SELECT i.ItemID,i.LastModifiedBy,i.LastModifiedDate,

field1 =
CASE i.field1
WHEN d.field1 THEN NULL
ELSE i.field1
END,

field2 =
CASE i.field2
WHEN d.field2 THEN NULL
ELSE i.field2
END,

field3 =
CASE i.field3
WHEN d.field3 THEN NULL
ELSE i.field3
END,

field4 =
CASE i.field4
WHEN d.field4 THEN NULL
ELSE i.field4
END,

field5 =
CASE i.field5
WHEN d.field5 THEN NULL
ELSE i.field5
END,

GETDATE()

FROM inserted i
INNER JOIN deleted d
ON i.ItemID = d.ItemID

Como você pode ver, estou comparando os valores de cadacampo nas tabelas excluídas e inseridas e apenas gravando o valor do campo da tabela inserida na tabela de auditoria se elas diferirem, caso contrário, apenas escrevo NULL.

Isso certamente funciona para mim. Alguém pode ver algum problema com essa abordagem? Minha equipe possui tanto o aplicativo quanto o banco de dados para que possíveis bolas curvas, como as alterações de esquema, sejam cobertas.


1 para resposta № 6

A outra maneira de fazer isso além de gatilhos é isso,

  1. Tem quatro colunas UpdFlag, DelFlag, EffectiveDate e TerminatedDate para cada tabela em que você deseja fazer uma trilha de auditoria.
  2. codifique seu sproc "s de tal maneira que quando você fizer uma atualização, passe os dados da coluna de todas as linhas para o sproc, atualize a linha configurando TerminatedDate para a data que foi atualizada, e marcar o UpdFlag e colocar o datetime na coluna
  3. Em seguida, crie uma nova linha com os novos dados (o que é realmente atualizado). e colocar em uma nova data agora para o EffectiveDate e a TerminatedDate definido para a data máxima.

Da mesma forma, se você quiser fazer uma exclusão da linha, basta atualizar a linha marcando a linha DelFlag como definido, o TerminatedDate com o datetime agora. Você está, na verdade, fazendo uma exclusão suave e não uma exclusão real do SQL.

Dessa forma, quando você deseja auditar os dados e mostrar um rastro das alterações, basta filtrar as linhas daqueles que têm UpdFlag conjunto ou entre EffectiveDate e TerminatedDate. Da mesma forma para aqueles que foram excluídos, você filtrar para aqueles que têm o DelFlag conjunto ou entre EffectiveDate e TerminatedDate. Para as linhas atuais, filtre as linhas que possuem os dois sinalizadores. A vantagem é que você não precisa criar outra tabela para a auditoria quando o gatilho é usado!


0 para resposta № 7

Eu ia rota gatilhos, criando mesa comestrutura semelhante a uma atualizada, com colunas adicionais para rastrear alterações como ModifiedAt etc. E, em seguida, adicionando o gatilho de atualização que inserirá alterações nessa tabela. Eu acho mais fácil de manter do que ter tudo no código do aplicativo. Claro que muitas pessoas tendem a esquecer gatilhos quando se trata de questões como "wtf esta tabela está mudando";) Felicidades.