Frage

Ich habe eine Lösung mit der Entwicklung, die verfolgten Änderungen an eine Datenbank beauftragt worden.

Für Updates muss ich erfassen:

  • Datum der Aktualisierung
  • Altwert
  • neuer Wert
  • Feld betroffen
  • Person zu tun ändern
  • Rekord-ID
  • Tabellensatz ist in

Für Löschungen:

  • Datum löschen
  • Person löschen tun
  • Der Titel / Beschreibung / id der Datensatz gelöscht. Die Tabellen I Tracking ist Änderungen auf alle haben einen Titel oder eine Beschreibung Feld. Ich möchte, dies erfassen, bevor der Datensatz gelöscht wird.
  • Tabellensatz war in

Für Einsätze:

  • Datum des Einsatzes
  • Person zu tun ändern
  • Rekord-ID
  • Tabellensatz ist in

Ich habe gedacht, ein paar Möglichkeiten, dies zu tun:

  • Ich bin mit gespeicherten Prozeduren für Aktualisierungen / löscht / Einsätze. Ich würde eine generische „Tracking“ Tabelle erstellen. Es wäre genug Felder haben, um alle Daten zu erfassen. Ich würde dann eine weitere Zeile in jeder gespeicherte Prozedur auf die Wirkung von „Datensatz einfügen in Nachverfolgungstabelle“ hinzufügen.
    • Nachteil: alle Aktualisierungen / Löschungen / Inserts alle durcheinander in der gleichen Tabelle sind
    • viele Nulled Felder
    • Wie erfasse ich Batch-Updates / löscht / Einsätze? <---- könnte dies kein Problem sein. Ich weiß nicht wirklich irgend etwas wie dies in der Anwendung.
    • , wie ich den Benutzer erfasse das Update zu machen. Die Datenbank nur sieht ein Konto.
    • bearbeitet viele vorhandenen Code zu bearbeiten.
  • Schließlich konnte ich einen Trigger erstellen, die nach Updates / löscht / Einsätze genannt wird. Viele der gleichen Nachteile wie die erste Lösung, außer: Ich hätte so viel Code bearbeiten. Ich bin nicht sicher, wie ich Updates zu verfolgen. Es sieht nicht wie es eine Möglichkeit, Trigger mit kürzlich aktualisierten Datensätze zu sehen.

Ich verwende asp.net, C #, SQL Server 2005, iis6, Fenster 2003. Ich kein Budget haben so leider kann ich nichts kaufen mir dabei zu helfen.

Vielen Dank für Ihre Antworten!

War es hilfreich?

Lösung

Ein Trigger würde nicht alle Informationen, die Sie für eine Reihe von Gründen brauchen - aber keine Benutzer-ID ist das entscheidende Argument

.

Ich würde sagen, Sie auf dem richtigen Weg mit einem gemeinsamen sp sind einzusetzen, wo immer eine Änderung vorgenommen wird. Wenn Sie auf SPs für Ihre Schnittstellen sind Standardisierung, dann sind Sie vor dem Spiel - es wird schwer sein, in einem Wechsel zu schleichen, die nicht verfolgt wird,

.

Schauen Sie sich diese als äquivalent eine Audit-Trail in einer Buchhaltungsanwendung - das ist das Journal - eine einzige Tabelle mit jeder Transaktion aufgezeichnet. Sie würden nicht implementieren getrennte Zeitschriften für Einzahlungen, Auszahlungen, Anpassungen usw. und dies ist das gleiche Prinzip.

Andere Tipps

Ich hasse die Frage nach der Seite Schritt und ich weiß, Sie kein Budget haben, aber die einfachste Lösung wird auf SQL Server aktualisieren 2008. Es hat diese Funktion in gebaut. Ich dachte, dass zumindest sollte sonst für jedermann erwähnt werden, die in dieser Frage kommt, auch wenn Sie es nicht selbst verwenden können.

(Unter den einsetzbaren Editionen von SQL 2008, ist diese Funktion in Enterprise verfügbar ist.)

Ich würde vorschlagen, Sie 2 Spalte in jeder Tabelle zu verwenden. Namen rowhistory und IsDeleted und der Datentyp wird xml und Bit sein. Löschen Sie niemals die Zeilen, immer verwenden Flagge IsDeleted Nun gehen Sie mit Update-Trigger. Ich gebe Ihnen Beispiel für die gleiche Ich habe diese eine Tabelle namens Seite

    CREATE TABLE te_Page([Id] [int] IDENTITY(1,1) NOT NULL, [Name] [varchar](200) NOT NULL, [Description] [varchar](200) NULL,[CreatedBy] [uniqueidentifier] NULL, [CreatedDate] [datetime] NOT NULL, [UpdatedBy] [uniqueidentifier] NULL, [UpdatedDate] [datetime] NULL, [IsDeleted] [bit] NULL, [RowHistory] [xml] NULL, CONSTRAINT [PK_tm_Page] PRIMARY KEY CLUSTERED ([Id] ASC )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY] ) ON [PRIMARY]

Jetzt nach Erstellen der Tabelle alles, was Sie tun müssen, ist fügen Sie Kopie den Code unten und Ihre Aufgabe wird für Seite Tabelle. Es beginnt die Geschichte der Reihe in der gleichen Reihe der Aufnahme, die zusammen mit alten und neuen Werten aktualisiert wird.

                ALTER Trigger [dbo].[Trg_Te_Page]    
        On [dbo].[te_Page]                
        After Update                
        As                 
        --If @@rowcount = 0 Or Update(RowHistory)    
        --Return    

        Declare @xml NVARCHAR(MAX)     
        Declare @currentxml NVARCHAR(MAX)   
        Declare @node NVARCHAR(MAX)    
        Declare @ishistoryexists XML    

        Declare @FormLineAttributeValueId int  

        -- new Values  
        Declare @new_Name varchar(200)  
        Declare @new_Description varchar(200)  

        Declare @new_CreatedBy UNIQUEIDENTIFIER    
        Declare @new_CreatedDate DATETIME    
        Declare @new_UpdatedBy UNIQUEIDENTIFIER    
        Declare @new_UpdatedDate DATETIME    
        Declare @new_IsDeleted BIT  

        --old values  
        Declare @old_Name varchar(200)  
        Declare @old_Description varchar(200)  

        Declare @old_CreatedBy UNIQUEIDENTIFIER    
        Declare @old_CreatedDate DATETIME    
        Declare @old_UpdatedBy UNIQUEIDENTIFIER    
        Declare @old_UpdatedDate DATETIME    
        Declare @old_IsDeleted BIT  


        -- declare temp fmId  
        Declare @fmId int  
        -- declare cursor  
        DECLARE curFormId cursor   
        FOR select Id from INSERTED   
        -- open cursor       
        OPEN curFormId  
        -- fetch row  
        FETCH NEXT FROM curFormId INTO @fmId  

        WHILE @@FETCH_STATUS  = 0   
        BEGIN   

        Select   
        @FormLineAttributeValueId = Id,   
        @old_Name = Name,  
        @old_Description = [Description],  

        @old_CreatedBy = CreatedBy,    
        @old_CreatedDate =CreatedDate,  
        @old_UpdatedBy =UpdatedBy,    
        @old_UpdatedDate =UpdatedDate,  
        @old_IsDeleted  = IsDeleted,  
        @currentxml = cast(RowHistory as NVARCHAR(MAX))  
        From DELETED where Id=@fmId  



        Select      
        @new_Name = Name,  
        @new_Description = [Description],  

        @new_CreatedBy = CreatedBy,    
        @new_CreatedDate =CreatedDate,  
        @new_UpdatedBy =UpdatedBy,    
        @new_UpdatedDate =UpdatedDate,  
        @new_IsDeleted  = IsDeleted  
        From INSERTED where Id=@fmId  

        set @old_Name = Replace(@old_Name,'&','&amp;')
        set @old_Name = Replace(@old_Name,'>','&gt;')  
        set @old_Name = Replace(@old_Name,'<','&lt;')     
        set @old_Name = Replace(@old_Name,'"','&quot;')
        set @old_Name = Replace(@old_Name,'''','&apos;')          

        set @new_Name = Replace(@new_Name,'&','&amp;')      
        set @new_Name = Replace(@new_Name,'>','&gt;')  
        set @new_Name = Replace(@new_Name,'<','&lt;')     
        set @new_Name = Replace(@new_Name,'"','&quot;')
        set @new_Name = Replace(@new_Name,'''','&apos;') 

        set @old_Description = Replace(@old_Description,'&','&amp;')
        set @old_Description = Replace(@old_Description,'>','&gt;')  
        set @old_Description = Replace(@old_Description,'<','&lt;')     
        set @old_Description = Replace(@old_Description,'"','&quot;')
        set @old_Description = Replace(@old_Description,'''','&apos;')          

        set @new_Description = Replace(@new_Description,'&','&amp;')      
        set @new_Description = Replace(@new_Description,'>','&gt;')  
        set @new_Description = Replace(@new_Description,'<','&lt;')     
        set @new_Description = Replace(@new_Description,'"','&quot;')
        set @new_Description = Replace(@new_Description,'''','&apos;')   

        set @xml = ''     

        BEGIN      

        -- for Name  
        If ltrim(rtrim(IsNull(@new_Name,''))) != ltrim(rtrim(IsNull(@old_Name,'')))    
        set @xml = @xml + '<ColumnInfo ColumnName="Name" OldValue="'+ @old_Name + '" NewValue="' + @new_Name + '"/>'    

        -- for Description  
        If ltrim(rtrim(IsNull(@new_Description,''))) != ltrim(rtrim(IsNull(@old_Description,'')))    
        set @xml = @xml + '<ColumnInfo ColumnName="Description" OldValue="'+ @old_Description + '" NewValue="' + @new_Description + '"/>'    

        -- CreatedDate     
        If IsNull(@new_CreatedDate,'') != IsNull(@old_CreatedDate,'')  
        set @xml = @xml + '<ColumnInfo ColumnName="CreatedDate" OldValue="'+ cast(isnull(@old_CreatedDate,'') as varchar(100)) + '" NewValue="' + cast(isnull(@new_CreatedDate,'') as varchar(100)) + '"/>'    

        -- CreatedBy     
        If cast(IsNull(@new_CreatedBy,'00000000-0000-0000-0000-000000000000')as varchar (36)) != cast(IsNull(@old_CreatedBy,'00000000-0000-0000-0000-000000000000')as varchar(36))    
        set @xml = @xml + '<ColumnInfo ColumnName="CreatedBy" OldValue="'+ cast(IsNull(@old_CreatedBy,'00000000-0000-0000-0000-000000000000') as varchar(36)) + '" NewValue="' + cast(isnull(@new_CreatedBy,'00000000-0000-0000-0000-000000000000') as varchar(36))+
        '"/>'    

        -- UpdatedDate       
        If IsNull(@new_UpdatedDate,'') != IsNull(@old_UpdatedDate,'')    
        set @xml = @xml + '<ColumnInfo ColumnName="UpdatedDate" OldValue="'+ cast(IsNull(@old_UpdatedDate,'') as varchar(100)) + '" NewValue="' + cast(IsNull(@new_UpdatedDate,'') as varchar(100)) + '"/>'    

        -- UpdatedBy     
        If cast(IsNull(@new_UpdatedBy,'00000000-0000-0000-0000-000000000000') as varchar(36)) != cast(IsNull(@old_UpdatedBy,'00000000-0000-0000-0000-000000000000') as varchar(36))    
        set @xml = @xml + '<ColumnInfo ColumnName="UpdatedBy" OldValue="'+ cast(IsNull(@old_UpdatedBy,'00000000-0000-0000-0000-000000000000') as varchar(36)) + '" NewValue="' + cast(IsNull(@new_UpdatedBy,'00000000-0000-0000-0000-000000000000') as varchar(36))+
        '"/>'    

        -- IsDeleted  
        If cast(IsNull(@new_IsDeleted,'') as varchar(10)) != cast(IsNull(@old_IsDeleted,'') as varchar(10))    
        set @xml = @xml + '<ColumnInfo ColumnName="IsDeleted" OldValue="'+ cast(IsNull(@old_IsDeleted,'') as varchar(10)) + '" NewValue="' + cast(IsNull(@new_IsDeleted,'') as varchar(10)) + '" />'    

        END    

        Set @xml = '<RowInfo TableName="te_Page" UpdatedBy="' + cast(IsNull(@new_UpdatedBy,'00000000-0000-0000-0000-000000000000') as varchar(50)) +  '" UpdatedDate="' + Convert(Varchar(20),GetDate()) + '">' + @xml + '</RowInfo>'    
        Select @ishistoryexists = RowHistory From DELETED     

        --print @ishistoryexists  


        If @ishistoryexists is null    
        Begin     
        Set @xml = '<History>' + @xml + '</History>'      
        Update te_Page    
        Set    
        RowHistory = @xml    
        Where     
        Id = @FormLineAttributeValueId    

        End    

        Else    
        Begin     
        set @xml = REPLACE(@currentxml, '<History>', '<History>' + @xml)  
        Update te_Page  
        Set  
        RowHistory = @xml  
        Where   
        Id = @FormLineAttributeValueId     
        End  


        FETCH NEXT FROM curFormId INTO @fmId  
        END   


        CLOSE curFormId  
        DEALLOCATE curFormId  

Nun, wenn wird führen Sie eine Aktualisierung Ihrer Daten in gespeichert wird rowhistory Spalte

Ein Weg, ich habe diese behandelt gesehen (obwohl ich es nicht empfehlen würde, ehrlich) ist es über gespeicherte Prozeduren zu handhaben, vorbei an dem Benutzer-ID / Benutzername / was auch immer als Parameter. Die gespeicherten Prozeduren würden ein Protokollieren nennen, die die entsprechenden Angaben in einer zentralen Log-Tabelle geschrieben.

Hier ist, wo es ein bisschen whacky bekam, obwohl ...

Für INSERTs / updates, die entsprechende Zeile (n) in der Tabelle als XML-Daten gespeichert, sobald die INSERT / UPDATE erfolgreich abgeschlossen hatte. Für DELETEs wurde die Zeile vor dem DELETE ausgeführt wird gespeichert (obwohl, realistisch, sie hätten es von der DELETE-Anweisung der Ausgabe bekommen - zumindest mit SQL Server 2005)

.

Wenn ich mich richtig erinnere, der Tisch hatte nur ein paar Spalten: Benutzer-ID, Datetime der Protokollierung, Art der Transaktion (I / U / D), XML-Daten die entsprechenden Zeilen, Tabellennamen enthalten, und Primärschlüsselwert (in erster Linie verwendet, für schnelle Suche, was zeichnet sie wollten).

Viele Wege führen nach Rom, aber ...

Mein Rat ist, einfach zu halten ist. später erweitern Sie es heraus, wenn / wenn Sie müssen.

Wenn Sie die Möglichkeit haben, dies zu tun, sperren Benutzer nach unten nur in der Lage sein, über gespeicherte Prozeduren auszuführen umsetzbare Anweisungen für Tabellen und dann die Protokollierung behandeln (wie Sie wollen) von dort.

bauten wir unsere eigene und brauchte nur der Benutzer und PC in jeder weitergegeben hinzufügen / update gespeicherte Prozedur. es ist dann nur eine Frage der den ursprünglichen Datensatz bekommen adn die Variablen bevölkern und sie an den übergebenen Variablen und Protokollierung der Daten an unseren Tisch zu vergleichen. für löscht wir haben nur eine Kopie der Ursprungs Tabellen + ein Zeitstempel-Feld so wird der Datensatz nie wirklich gelöscht und können jederzeit wiederhergestellt werden, müssen wir (natürlich die Löschroutine prüft, ob FK Beziehungen und so weiter).

hinzufügen / Update-Log-Tabelle sieht aus wie Terminzeit, Tabellenname, Spaltenname, record_id, old_value, neuer Wert, Benutzeridentifikation, Computer

wir nie Nullen einzufügen, damit wir sie konvertieren Strings zu leeren, neue Einträge mit dem Vermerk ‚{Neueintrag}‘ in der old_value Spalte. record_id besteht aus so vielen Schlüsselspalten eindeutig, dass die einzelnen Datensatz zu identifizieren (field1 + ‚‘ + field2 + ...)

Zunächst einmal, in allen Tabellen sollten Sie zumindest diese Spalten zu den Datenspalten hinzugefügt Datecreated, nutzererzeugte, DateModified, userModified. Möglicherweise möchten Sie vielleicht einen „Status“ oder „LastAction“ Spalte hinzufügen, so dass Sie nicht immer tatsächlich eine Zeile löschen Sie setzen es nur auf ein gelöschtes / eingefügt / aktualisiert Status. Als nächstes können Sie eine „History-Tabelle“ erstellen, die eine exakte Kopie der ersten Tabelle ist. Dann auf Aktualisierungen oder Löschungen hat den Auslöser die gelöschten Tabelleneinträge in die History-Tabelle kopieren Sie die DateModified, userModified und Statusfelder zur gleichen Zeit zu ändern.

Ich habe ein Setup in SQL Server, wo wir Ansichten verwenden würden unsere Daten zuzugreifen, die Einsätze behandeln würde, Aktualisierungen und Löschungen mit INSTEAD OF-Trigger.

. Zum Beispiel: ein STATT DELETE Auslöser für die Sicht würde die Datensätze in der zugrunde liegenden Tabelle markieren als gelöscht und die Ansicht gefiltert wurde nicht gelöscht Aufzeichnungen zeigen

In allen Triggern wir eine Änderungsdatum und Benutzernamen aktualisiert. Das Problem ist, dass die Datenbank-Benutzername anmeldet, die nicht das gleiche wie der ultimative Anwendung Benutzername ist.

Die Ansicht muss Schema für diese gebunden sein zu arbeiten.

über Benutzer anmelden, das ändert DB: Sie können beliebig viele SQL-Benutzer erstellen, wie Sie für Ihre DB benötigen und wenn Sie verwenden, um Sitzungen und eingeschränkten / registrierte Zugriff auf Ihr Programm / script Sie können diese Informationen verwenden, um verschiedene DB-Verbindungseinstellungen (d Benutzername) einzuleiten, vor jedem Betrieb mit DB.

Mindestens das sollte für PHP-Skripte weise machbar sein, aber ich könnte für asp.net falsch sein.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top