Controleer of er wijzigingen in een SQL Server-tabel?

stemmen
122

Hoe kan ik een SQL Server-database voor wijzigingen in een tabel zonder gebruik te maken triggers of wijzigen van de structuur van de database op enigerlei wijze te controleren? Mijn voorkeur programmeeromgeving is .NET en C #.

Ik zou graag in staat zijn om elke vorm van steun SQL Server 2000 SP4 of nieuwer. Mijn toepassing is een bolt-on data visualisatie voor het product van een ander bedrijf. Ons klantenbestand is in de duizenden, dus ik wil niet te hebben eisen dat we de tafel van de third-party leverancier bij elke installatie te wijzigen in te zetten.

Door verandert in een tafel Ik bedoel wijzigingen aan tafel gegevens, geen wijzigingen in de structuur van tabellen.

Uiteindelijk wil ik de wijziging van een gebeurtenis te activeren in mijn toepassing, in plaats van te controleren veranderingen op een interval.


De beste manier van handelen gegeven mijn eisen (geen triggers of schema wijziging, SQL Server 2000 en 2005) lijkt te zijn om het te gebruiken BINARY_CHECKSUMfunctie in T-SQL . De manier waarop ik van plan uit te voeren is dit:

Elke X seconden voert u de volgende vraag:

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

En vergelijk dat ten opzichte van de opgeslagen waarde. Als de waarde is veranderd, ga door de tabel rij voor rij met behulp van de query:

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

En vergelijk de teruggekeerde checksums tegen opgeslagen waarden.

De vraag is gesteld op 01/08/2008 om 13:35
bron van user
In andere talen...                            


8 antwoorden

stemmen
25

Waarom ga je niet wilt triggers gebruiken? Ze zijn een goede zaak als je ze correct te gebruiken. Als je ze te gebruiken als een manier om referentiële integriteit af te dwingen dat is wanneer ze gaan van goed naar slecht. Maar als je ze gebruikt voor het bewaken, zijn ze niet echt beschouwd als taboe.

antwoordde op 01/08/2008 om 14:07
bron van user

stemmen
18

Heeft u een DTS baan (of een baan die wordt gestart door een Windows-service) die wordt uitgevoerd op een gegeven interval. Elke keer dat het wordt uitgevoerd, krijgt informatie over het gegeven tafel met behulp van het systeem INFORMATION_SCHEMA tabellen en registreert deze gegevens in de data repository. Vergelijk de geretourneerde gegevens over de structuur van de tafel met de geretourneerde gegevens van de vorige keer. Als het anders is, dan weet je dat de structuur is veranderd.

Voorbeeld vraag om informatie terug te keren met betrekking tot alle van de kolommen in tabel ABC (idealiter een opsomming uit slechts de kolommen van de INFORMATION_SCHEMA tabel die u wilt, in plaats van het gebruik van * selecteren ** zoals ik hier te doen):

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

Je zou verschillende kolommen en uitzicht INFORMATION_SCHEMA controleren, afhankelijk van hoe je precies "verandert in een tafel" te definiëren.

antwoordde op 01/08/2008 om 15:06
bron van user

stemmen
90

Neem een ​​kijkje op het CHECKSUM commando:

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

Dat zal hetzelfde aantal keren elke keer dat het wordt gerund, zolang de inhoud tabel niet zijn veranderd. Zie mijn post op deze voor meer informatie:

CHECKSUM

Hier is hoe ik het gebruikt om cache afhankelijkheden te herbouwen wanneer tafels veranderd:
ASP.NET 1.1-database cache afhankelijkheid (zonder triggers)

antwoordde op 02/08/2008 om 06:20
bron van user

stemmen
19

Hoe vaak heb je nodig om te controleren op veranderingen en hoe groot (in termen van rij-formaat) zijn de tabellen in de database? Indien u het gebruik CHECKSUM_AGG(BINARY_CHECKSUM(*))methode van John voorgesteld, zal het elke rij van de opgegeven tabel te scannen. De NOLOCKhint helpt, maar op een grote database, bent u nog steeds elke rij raken. Je moet ook de checksum op te slaan voor elke rij, zodat je vertellen één is veranderd.

Heeft u overwogen gaan op dit vanuit een andere hoek? Als u niet wilt dat het schema om triggers toe te voegen, te wijzigen (die een logisch is, het is niet jouw database), Hebt u overwogen het werken met de leverancier van de toepassing die maakt de database?

Ze konden een API die een mechanisme voor het melden accessoire apps die data is veranderd biedt implementeren. Het kan zo simpel zijn als het schrijven naar een melding tabel die laat zien wat tafel en welke rij werden gewijzigd zijn. Dat kan worden uitgevoerd door middel van triggers of applicatiecode. Van uw kant, zou ti niet uit, je enige zorg zou worden het scannen van de kennisgeving tafel op een periodieke basis. De performance hit op de database zou veel minder dan elke rij scannen voor veranderingen.

Het harde deel zou overtuigen van de leverancier van de applicatie om deze functie uit te voeren. Aangezien dit handgrepen volledig kan worden door middel van SQL via triggers, kan je het grootste deel van het werk voor hen te doen door het schrijven en testen van de triggers en dan brengen de code om de leverancier van de toepassing. Door de ondersteuning van de leverancier van de triggers, te voorkomen dat de situatie waarin je het toevoegen van een trekker per ongeluk vervangt een door de leverancier geleverde trigger.

antwoordde op 03/08/2008 om 14:59
bron van user

stemmen
13

Wilde gok hier: Als u niet wilt tabellen van de derde partij te wijzigen, kunt u een weergave maken en vervolgens een trigger op deze mening?

antwoordde op 05/08/2008 om 02:12
bron van user

stemmen
17

Helaas, ik denk niet dat er een schone manier om dit te doen in SQL2000. Als u uw wensen beperken tot SQL Server 2005 (en later), dan bent u in het bedrijfsleven. U kunt het gebruiken SQLDependencyklasse System.Data.SqlClient. Zie Query Meldingen in SQL Server (ADO.NET) .

antwoordde op 06/08/2008 om 02:54
bron van user

stemmen
30

Helaas CHECKSUM niet altijd goed werken om veranderingen te detecteren . Het is slechts een primitieve checksum en geen CRC berekening. Daarom kun je niet gebruiken om alle wijzigingen op te sporen, bijvoorbeeld symmetrische wijzigingen resulteren in dezelfde CHECKSUM!

Bijv. de oplossing met CHECKSUM_AGG(BINARY_CHECKSUM(*))levert altijd 0 voor alle 3 tafels met verschillende inhoud!


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!

antwoordde op 30/03/2011 om 13:07
bron van user

stemmen
7

Controleer de laatste commit datum. Elke databank heeft een geschiedenis van wanneer iedere commit wordt gemaakt. Ik denk dat het een standaard van ACID compliance.

antwoordde op 24/07/2014 om 05:58
bron van user

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