Verificar se há alterações a uma tabela do SQL Server?

votos
122

Como posso monitorar um banco de dados do SQL Server para alterações em uma tabela sem o uso de gatilhos ou modificar a estrutura do banco de dados de alguma forma? Meu ambiente de programação preferida é .NET e C #.

Eu gostaria de ser capaz de suportar qualquer Server 2000 SQL SP4 ou mais recente. Meu aplicativo é uma visualização de dados bolt-on para o produto de outra empresa. Nossa base de clientes está na casa dos milhares, então eu não quero ter que colocar em requisitos que modificar a tabela do fornecedor de terceiros em cada instalação.

Por alterações em uma tabela Quero dizer alterações para os dados da tabela, e não alterações na estrutura da tabela.

Finalmente, eu gostaria que a mudança para acionar um evento no meu aplicativo, em vez de ter que verificar se há mudanças em um intervalo.


O melhor curso de ação dadas as minhas necessidades (sem gatilhos ou modificação de esquema, Server 2000 e 2005 SQL) parece ser a de usar a BINARY_CHECKSUMfunção em T-SQL . A maneira que eu pretendo implementar é esta:

A cada X segundos execute a seguinte consulta:

SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*))
FROM sample_table
WITH (NOLOCK);

E comparar isso com o valor armazenado. Se o valor foi alterado, atravessar a linha da tabela por linha usando a consulta:

SELECT row_id, BINARY_CHECKSUM(*)
FROM sample_table
WITH (NOLOCK);

E comparar as somas de verificação devolvidos contra os valores armazenados.

Publicado 01/08/2008 em 13:35
fonte usuário
Em outras línguas...                            


8 respostas

votos
90

Dê uma olhada no comando CHECKSUM:

SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM sample_table WITH (NOLOCK);

Que irá devolver o mesmo número cada vez que é executado, contanto que o conteúdo da tabela não mudaram. Veja meu post sobre isso para mais informações:

CHECKSUM

Veja como eu usei-o para reconstruir as dependências de cache quando as tabelas alteradas:
dependência ASP.NET cache de 1,1 banco de dados (sem gatilhos)

Respondeu 02/08/2008 em 06:20
fonte usuário

votos
30

Infelizmente CHECKSUM não funciona sempre adequadamente para detectar alterações . É apenas uma soma de verificação primitiva e nenhum cálculo CRC. Portanto, você não pode usá-lo para detectar todas as alterações, mudanças por exemplo simétricas resultar na mesma soma de verificação!

Por exemplo. a solução com CHECKSUM_AGG(BINARY_CHECKSUM(*))entrega sempre 0 para todas as 3 tabelas com conteúdo diferente!


SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM 
(
  SELECT 1 as numA, 1 as numB
  UNION ALL
  SELECT 1 as numA, 1 as numB
)  q
-- delivers 0!

SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM ( SELECT 1 as numA, 2 as numB UNION ALL SELECT 1 as numA, 2 as numB ) q -- delivers 0!

SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM ( SELECT 0 as numA, 0 as numB UNION ALL SELECT 0 as numA, 0 as numB ) q -- delivers 0!

Respondeu 30/03/2011 em 13:07
fonte usuário

votos
25

Por que você não quer usar gatilhos? Eles são uma coisa boa se você usá-los corretamente. Se você usá-los como uma forma de impor a integridade referencial, que é quando eles vão de bom para ruim. Mas se você usá-los para o monitoramento, eles não são realmente considerado tabu.

Respondeu 01/08/2008 em 14:07
fonte usuário

votos
19

Quantas vezes você precisa verificar se há mudanças e quão grande (em termos de tamanho de linha) são as tabelas no banco de dados? Se você usar o CHECKSUM_AGG(BINARY_CHECKSUM(*))método sugerido por John, ele irá verificar todas as linhas da tabela especificada. A NOLOCKdica ajuda, mas em um grande banco de dados, você ainda está acertando todas as linhas. Você também vai precisar para armazenar a soma de verificação para cada linha para que você diga uma mudou.

Você já considerou indo para isso de um ângulo diferente? Se você não quiser modificar o esquema para adicionar gatilhos, (que faz certo sentido, não é o seu banco de dados), você considerou trabalhar com o fornecedor do aplicativo que faz o banco de dados?

Eles poderiam implementar uma API que fornece um mecanismo para notificar aplicativos de acessório que os dados foram alterados. Poderia ser tão simples como escrever a uma tabela de notificação que lista o que mesa e qual linha foram modificados. Isso poderia ser implementada através de gatilhos ou código do aplicativo. De seu lado, ti não importa, sua única preocupação seria a digitalização tabela de notificação em uma base periódica. O desempenho atingido no banco de dados seria muito menos do que a digitalização de cada linha para mudanças.

A parte mais difícil seria convencer o fornecedor da aplicação para implementar este recurso. Uma vez que este pode ser alças inteiramente através de SQL via gatilhos, você poderia fazer a maior parte do trabalho para eles, escrevendo e testando os gatilhos e, em seguida, trazendo o código para o fornecedor do aplicativo. Por ter o suporte do fornecedor os gatilhos, é evitar a situação em que o seu adicionando um gatilho inadvertidamente substitui um gatilho fornecido pelo fornecedor.

Respondeu 03/08/2008 em 14:59
fonte usuário

votos
18

Tem um trabalho DTS (ou um trabalho que é iniciado por um serviço de janelas), que é executado em um determinado intervalo. Cada vez que é executado, ele recebe informações sobre a tabela dada usando o sistema INFORMATION_SCHEMA mesas, e registra esses dados no repositório de dados. Compare os dados retornados em relação à estrutura da tabela com os dados retornados da vez anterior. Se for diferente, então você sabe que a estrutura foi alterada.

consulta exemplo para retornar informações sobre todas as colunas em ABC mesa (de preferência listando apenas as colunas da tabela INFORMATION_SCHEMA que você quer, em vez de usar * selecionar ** como eu faço aqui):

select * from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = 'ABC'

Você iria acompanhar diferentes colunas e exibições INFORMATION_SCHEMA dependendo de como exatamente você define "muda para uma mesa".

Respondeu 01/08/2008 em 15:06
fonte usuário

votos
17

Infelizmente, eu não acho que há uma maneira limpa para fazer isso em SQL2000. Se você restringir suas exigências para o SQL Server 2005 (e mais tarde), então você está no negócio. Você pode usar a SQLDependencyclasse em System.Data.SqlClient. Ver notificações de consulta em SQL Server (ADO.NET) .

Respondeu 06/08/2008 em 02:54
fonte usuário

votos
13

palpite aqui: Se você não quiser modificar as tabelas do terceiro partido, você pode criar um ponto de vista e, em seguida, colocar um gatilho em que ponto de vista?

Respondeu 05/08/2008 em 02:12
fonte usuário

votos
7

Verifique a última confirmação de data. Cada banco de dados tem uma história de quando cada commit é feito. Eu acredito que é um padrão de conformidade ACID.

Respondeu 24/07/2014 em 05:58
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more