none
Änderung eines Feldes protokollieren RRS feed

  • Frage

  • Hallo zusammen,

    ich vermute, dass jemand in einer meiner SQL Tabellen unerlaubt Werte ändert. Daraus bekommt unsere Applikation manchmal einen Zugriffsfehler.

    Nun wollte ich protokollieren, welcher User zu welcher Zeit auf diese Tabelle (besser noch auf ein bestimmtes Feld) mit ALTER zugreift.

    Ich habe versucht einen DDL-Trigger zu erstellen. Hat aber irgendwie nicht richtig geklappt. (Konnte die Tabelle nicht angeben.)

    Hat jemand von euch ne Idee, die mir helfen könnte?

    Danke und Gruß

    Timo

    Mittwoch, 24. April 2013 08:11

Antworten

  • Hallo Timo,

    wenn jemand Werte ändert, wird das per INSERT, UPDATE, DELETE gemacht. ALTER ändert die Tabellen- und/oder Spaltendefinition.

    CREATE TRIGGER [dbo].[trg_DeinTrigger]
       ON  [dbo].[DeineTabelle]
       AFTER INSERT, UPDATE, DELETE
    AS 
    BEGIN
    
        SET NOCOUNT ON;
    
        -- Insert statements for trigger here
        INSERT INTO AndereTabelle
        (
            Spalte1, Spalte2, ...
        )
        SELECT ...
        FROM   inserted i
               LEFT JOIN deleted d ON i.IDSpalte = d.IDSpalte
    
    END

    So ähnlich könnte das dann bei dir aussehen.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community

    • Als Antwort vorgeschlagen Uwe RickenMVP Mittwoch, 24. April 2013 11:59
    • Als Antwort markiert TimoB_ Donnerstag, 25. April 2013 12:43
    Mittwoch, 24. April 2013 08:53
    Moderator
  • Hallo Timo,

    schau doch bitte nochmal in mein Beispiel. Für die neuen und (bei UPDATE und DELETE) alten Daten gibt es die Pseudotabellen inserted und deleted. Siehe dazu:

      http://msdn.microsoft.com/de-de/library/ms191300.aspx

    Diese musst Du verwenden, ansonsten kannst Du den bzw. die aktualisierten Datensätze (es können hier auch mehrere auf einmal eingefügt, aktualisiert oder gelöscht werden) nicht erkennen.

        INSERT INTO [changes]
        (
            ReferenzID, PLUInlayed, CreateDate, BoxTare, Loginuser, Changetime
        )
        SELECT ReferenzID, PLUInlayed, CreateDate, BoxTare, SUSER_SNAME(), GETDATE()
        FROM   inserted
    sollte in etwa passen. Anstelle von SUSER_SNAME() kann man auch ORIGINAL_LOGIN() nehmen, wenn man mit SQL Server 2005 oder höher arbeitet.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community



    • Bearbeitet Stefan FalzModerator Donnerstag, 25. April 2013 11:18
    • Als Antwort vorgeschlagen Olaf HelperMVP Donnerstag, 25. April 2013 11:23
    • Als Antwort markiert TimoB_ Donnerstag, 25. April 2013 12:43
    Donnerstag, 25. April 2013 11:14
    Moderator

Alle Antworten

  • Hallo Timo,

    wenn jemand Werte ändert, wird das per INSERT, UPDATE, DELETE gemacht. ALTER ändert die Tabellen- und/oder Spaltendefinition.

    CREATE TRIGGER [dbo].[trg_DeinTrigger]
       ON  [dbo].[DeineTabelle]
       AFTER INSERT, UPDATE, DELETE
    AS 
    BEGIN
    
        SET NOCOUNT ON;
    
        -- Insert statements for trigger here
        INSERT INTO AndereTabelle
        (
            Spalte1, Spalte2, ...
        )
        SELECT ...
        FROM   inserted i
               LEFT JOIN deleted d ON i.IDSpalte = d.IDSpalte
    
    END

    So ähnlich könnte das dann bei dir aussehen.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community

    • Als Antwort vorgeschlagen Uwe RickenMVP Mittwoch, 24. April 2013 11:59
    • Als Antwort markiert TimoB_ Donnerstag, 25. April 2013 12:43
    Mittwoch, 24. April 2013 08:53
    Moderator
  • Danke für den Tipp.

    komme heute nicht mehr zum testen. Aber ich probiers morgen mal und geb eine Rückmeldung.

    Mittwoch, 24. April 2013 15:10
  • Wollte es gerade ausprobieren. Aber irgendwie bekomme ich den insert in die Zieltabelle nicht hin.

    Wollte 3 Felder des geändert Datensatzes, den angemeldeten SQL-Benutzer und die Änderungsdatum, -zeit in die neue Tabelle schreiben.

    Hast du mir hierfür noch nen Tipp?

    Donnerstag, 25. April 2013 10:04
  • Hallo Timo,

    poste doch bitte mal dein SQL Statement, dass Du dafür verwendest hast.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community

    Donnerstag, 25. April 2013 10:10
    Moderator
  • CREATE TRIGGER [logging]
       ON  [dbo].[inlayed]
       AFTER INSERT, UPDATE, DELETE
    AS 
    BEGIN
    
        SET NOCOUNT ON;
    
        -- Insert statements for trigger here
        INSERT INTO [changes]
        (
            ReferenzID, PLUInlayed, CreateDate, BoxTare --, Loginuser, Changetime
        )
        SELECT ReferenzID, PLUInlayed, CreateDate, BoxTare
        FROM   inlayed

    Ich weiss gerade nicht, wie ich nur die Infos von dem geänderten Datensatz und zusätzlich den angemeldeten Benutzer sowie die Änderungszeit einfügen soll.

    Danke und Gruß

    Donnerstag, 25. April 2013 10:52
  • Hallo Timo,

    schau doch bitte nochmal in mein Beispiel. Für die neuen und (bei UPDATE und DELETE) alten Daten gibt es die Pseudotabellen inserted und deleted. Siehe dazu:

      http://msdn.microsoft.com/de-de/library/ms191300.aspx

    Diese musst Du verwenden, ansonsten kannst Du den bzw. die aktualisierten Datensätze (es können hier auch mehrere auf einmal eingefügt, aktualisiert oder gelöscht werden) nicht erkennen.

        INSERT INTO [changes]
        (
            ReferenzID, PLUInlayed, CreateDate, BoxTare, Loginuser, Changetime
        )
        SELECT ReferenzID, PLUInlayed, CreateDate, BoxTare, SUSER_SNAME(), GETDATE()
        FROM   inserted
    sollte in etwa passen. Anstelle von SUSER_SNAME() kann man auch ORIGINAL_LOGIN() nehmen, wenn man mit SQL Server 2005 oder höher arbeitet.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community



    • Bearbeitet Stefan FalzModerator Donnerstag, 25. April 2013 11:18
    • Als Antwort vorgeschlagen Olaf HelperMVP Donnerstag, 25. April 2013 11:23
    • Als Antwort markiert TimoB_ Donnerstag, 25. April 2013 12:43
    Donnerstag, 25. April 2013 11:14
    Moderator
  • CREATE TRIGGER [logging]
       ON  [dbo].[inlayed]
       AFTER INSERT, UPDATE, DELETE
    AS 
    BEGIN
    
        SET NOCOUNT ON;
    
        -- Insert statements for trigger here
     INSERT INTO [changes]
        (
            ReferenzID, PLUInlayed, CreateDate, BoxTare, Loginuser, Changetime
        )
        SELECT ReferenzID, PLUInlayed, CreateDate, BoxTare, ORIGINAL_LOGIN(), GETDATE()
        FROM   inserted

    Msg 102, Level 15, State 1, Procedure logging, Line 15

    Incorrect syntax near 'inserted'.

    Bekomme leider diese Fehlermeldung und in der Online Beschreibung kann ich nichts dazu finden.

    Donnerstag, 25. April 2013 12:07
  • Hallo Timo,

    da fehlt das END nach dem SQL Statement, also ganz am Ende des Triggercodes.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community

    Donnerstag, 25. April 2013 12:24
    Moderator
  • Hallo Timo,

    erweitere deine Tabellen "changes" mal noch um eine Spalte "Action" (nvarchar). Dann kannst Du auch den Trigger hier nehmen:

    ALTER TRIGGER [logging]
       ON  [dbo].[inlayed]
       AFTER INSERT, UPDATE, DELETE
    AS 
    BEGIN
    
    SET NOCOUNT ON;
    
    -- INSERT oder UPDATE
    IF EXISTS ( SELECT * FROM inserted )
        BEGIN
            INSERT INTO changes
            (
                Action, ReferenzID, PLUInlayed, CreateDate, BoxTare, Loginuser, Changetime
            )
            SELECT
                CASE
                    WHEN NOT EXISTS ( SELECT * FROM deleted ) THEN 'Inserted'
                    ELSE 'Updated'
                END,
                ReferenzID, PLUInlayed, CreateDate, BoxTare, ORIGINAL_LOGIN(), GETDATE()
            FROM inserted i
        END
    -- DELETE
    ELSE
        BEGIN
            INSERT INTO changes
            (
                Action, ReferenzID, PLUInlayed, CreateDate, BoxTare, Loginuser, Changetime
            )
            SELECT 'Deleted', ReferenzID, PLUInlayed, CreateDate, BoxTare, ORIGINAL_LOGIN(), GETDATE()
            FROM deleted d
        END
    END
    

    Damit hast Du dann auch gleich noch DELETE mit eingebaut und kannst in der changes Tabelle sehen, was mit dem Datensatz gemacht wurde (also INSERT, UPDATE oder DELETE)


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community

    Donnerstag, 25. April 2013 12:40
    Moderator
  • Oh je. Weiß nicht, wo ich meinen Kopf hatte.

    Jetzt funktionierts.

    Super.

    Danke.

    Danke auch noch für den Tipp mit dem Delete.


    • Bearbeitet TimoB_ Donnerstag, 25. April 2013 13:19
    Donnerstag, 25. April 2013 12:43