Sqlserver
 sql >> डेटाबेस >  >> RDS >> Sqlserver

एसक्यूएल सर्वर इतिहास तालिका - एसपी या ट्रिगर के माध्यम से पॉप्युलेट करें?

ट्रिगर।

हमने एक GUI लिखा (आंतरिक रूप से Red Matrix Reloaded . कहा जाता है) ) ऑडिट लॉगिंग ट्रिगर के आसान निर्माण/प्रबंधन की अनुमति देने के लिए।

यहां उपयोग की गई सामग्री के कुछ डीडीएल हैं:

ऑडिटलॉग टेबल

CREATE TABLE [AuditLog] (
    [AuditLogID] [int] IDENTITY (1, 1) NOT NULL ,
    [ChangeDate] [datetime] NOT NULL CONSTRAINT [DF_AuditLog_ChangeDate] DEFAULT (getdate()),
    [RowGUID] [uniqueidentifier] NOT NULL ,
    [ChangeType] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL ,
    [TableName] [varchar] (128) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL ,
    [FieldName] [varchar] (128) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL ,
    [OldValue] [varchar] (8000) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [NewValue] [varchar] (8000) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [Username] [varchar] (128) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL ,
    [Hostname] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL ,
    [AppName] [varchar] (128) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [UserGUID] [uniqueidentifier] NULL ,
    [TagGUID] [uniqueidentifier] NULL ,
    [Tag] [varchar] (8000) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
)

इन्सर्ट लॉग करने के लिए ट्रिगर करें

CREATE TRIGGER LogInsert_Nodes ON dbo.Nodes
FOR INSERT
AS

/* Load the saved context info UserGUID */
DECLARE @SavedUserGUID uniqueidentifier

SELECT @SavedUserGUID = CAST(context_info as uniqueidentifier)
FROM master.dbo.sysprocesses
WHERE spid = @@SPID

DECLARE @NullGUID uniqueidentifier
SELECT @NullGUID = '{00000000-0000-0000-0000-000000000000}'

IF @SavedUserGUID = @NullGUID
BEGIN
    SET @SavedUserGUID = NULL
END

    /*We dont' log individual field changes Old/New because the row is new.
    So we only have one record - INSERTED*/

    INSERT INTO AuditLog(
            ChangeDate, RowGUID, ChangeType, 
            Username, HostName, AppName,
            UserGUID, 
            TableName, FieldName, 
            TagGUID, Tag, 
            OldValue, NewValue)

    SELECT
        getdate(), --ChangeDate
        i.NodeGUID, --RowGUID
        'INSERTED', --ChangeType
        USER_NAME(), HOST_NAME(), APP_NAME(), 
        @SavedUserGUID, --UserGUID
        'Nodes', --TableName
        '', --FieldName
        i.ParentNodeGUID, --TagGUID
        i.Caption, --Tag
        null, --OldValue
        null --NewValue
    FROM Inserted i

अपडेट लॉग करने के लिए ट्रिगर करें

CREATE TRIGGER LogUpdate_Nodes ON dbo.Nodes
FOR UPDATE AS

/* Load the saved context info UserGUID */
DECLARE @SavedUserGUID uniqueidentifier

SELECT @SavedUserGUID = CAST(context_info as uniqueidentifier)
FROM master.dbo.sysprocesses
WHERE spid = @@SPID

DECLARE @NullGUID uniqueidentifier
SELECT @NullGUID = '{00000000-0000-0000-0000-000000000000}'

IF @SavedUserGUID = @NullGUID
BEGIN
    SET @SavedUserGUID = NULL
END

    /* ParentNodeGUID uniqueidentifier */
    IF UPDATE (ParentNodeGUID)
    BEGIN
        INSERT INTO AuditLog(
            ChangeDate, RowGUID, ChangeType, 
            Username, HostName, AppName,
            UserGUID, 
            TableName, FieldName, 
            TagGUID, Tag, 
            OldValue, NewValue)
        SELECT 
            getdate(), --ChangeDate
            i.NodeGUID, --RowGUID
            'UPDATED', --ChangeType
            USER_NAME(), HOST_NAME(), APP_NAME(), 
            @SavedUserGUID, --UserGUID
            'Nodes', --TableName
            'ParentNodeGUID', --FieldName
            i.ParentNodeGUID, --TagGUID
            i.Caption, --Tag
            d.ParentNodeGUID, --OldValue
            i.ParentNodeGUID --NewValue
        FROM Inserted i
            INNER JOIN Deleted d
            ON i.NodeGUID = d.NodeGUID
        WHERE (d.ParentNodeGUID IS NULL AND i.ParentNodeGUID IS NOT NULL)
        OR (d.ParentNodeGUID IS NOT NULL AND i.ParentNodeGUID IS NULL)
        OR (d.ParentNodeGUID <> i.ParentNodeGUID)
    END

    /* Caption varchar(255) */
    IF UPDATE (Caption)
    BEGIN
        INSERT INTO AuditLog(
            ChangeDate, RowGUID, ChangeType, 
            Username, HostName, AppName,
            UserGUID, 
            TableName, FieldName, 
            TagGUID, Tag, 
            OldValue, NewValue)
        SELECT 
            getdate(), --ChangeDate
            i.NodeGUID, --RowGUID
            'UPDATED', --ChangeType
            USER_NAME(), HOST_NAME(), APP_NAME(), 
            @SavedUserGUID, --UserGUID
            'Nodes', --TableName
            'Caption', --FieldName
            i.ParentNodeGUID, --TagGUID
            i.Caption, --Tag
            d.Caption, --OldValue
            i.Caption --NewValue
        FROM Inserted i
            INNER JOIN Deleted d
            ON i.NodeGUID = d.NodeGUID
        WHERE (d.Caption IS NULL AND i.Caption IS NOT NULL)
        OR (d.Caption IS NOT NULL AND i.Caption IS NULL)
        OR (d.Caption <> i.Caption)
    END

...

/* ImageGUID uniqueidentifier */
IF UPDATE (ImageGUID)
BEGIN
    INSERT INTO AuditLog(
        ChangeDate, RowGUID, ChangeType, 
        Username, HostName, AppName,
        UserGUID, 
        TableName, FieldName, 
        TagGUID, Tag, 
        OldValue, NewValue)
    SELECT 
        getdate(), --ChangeDate
        i.NodeGUID, --RowGUID
        'UPDATED', --ChangeType
        USER_NAME(), HOST_NAME(), APP_NAME(), 
        @SavedUserGUID, --UserGUID
        'Nodes', --TableName
        'ImageGUID', --FieldName
        i.ParentNodeGUID, --TagGUID
        i.Caption, --Tag
        (SELECT Caption FROM Nodes WHERE NodeGUID = d.ImageGUID), --OldValue
        (SELECT Caption FROM Nodes WHERE NodeGUID = i.ImageGUID) --New Value
    FROM Inserted i
        INNER JOIN Deleted d
        ON i.NodeGUID = d.NodeGUID
    WHERE (d.ImageGUID IS NULL AND i.ImageGUID IS NOT NULL)
    OR (d.ImageGUID IS NOT NULL AND i.ImageGUID IS NULL)
    OR (d.ImageGUID <> i.ImageGUID)
END

लॉग करने के लिए ट्रिगर हटाएं

CREATE TRIGGER LogDelete_Nodes ON dbo.Nodes
FOR DELETE
AS

/* Load the saved context info UserGUID */
DECLARE @SavedUserGUID uniqueidentifier

SELECT @SavedUserGUID = CAST(context_info as uniqueidentifier)
FROM master.dbo.sysprocesses
WHERE spid = @@SPID

DECLARE @NullGUID uniqueidentifier
SELECT @NullGUID = '{00000000-0000-0000-0000-000000000000}'

IF @SavedUserGUID = @NullGUID
BEGIN
    SET @SavedUserGUID = NULL
END

    /*We dont' log individual field changes Old/New because the row is new.
    So we only have one record - DELETED*/

    INSERT INTO AuditLog(
            ChangeDate, RowGUID, ChangeType, 
            Username, HostName, AppName,
            UserGUID, 
            TableName, FieldName, 
            TagGUID, Tag, 
            OldValue,NewValue)

    SELECT
        getdate(), --ChangeDate
        d.NodeGUID, --RowGUID
        'DELETED', --ChangeType
        USER_NAME(), HOST_NAME(), APP_NAME(), 
        @SavedUserGUID, --UserGUID
        'Nodes', --TableName
        '', --FieldName
        d.ParentNodeGUID, --TagGUID
        d.Caption, --Tag
        null, --OldValue
        null --NewValue
    FROM Deleted d

और यह जानने के लिए कि सॉफ़्टवेयर में किस उपयोगकर्ता ने अद्यतन किया है, प्रत्येक कनेक्शन एक संग्रहीत कार्यविधि को कॉल करके "स्वयं को SQL सर्वर पर लॉग करता है":

CREATE PROCEDURE dbo.SaveContextUserGUID @UserGUID uniqueidentifier AS

/* Saves the given UserGUID as the session's "Context Information" */
IF @UserGUID IS NULL
BEGIN
    PRINT 'Emptying CONTEXT_INFO because of null @UserGUID'
    DECLARE @BinVar varbinary(128)
    SET @BinVar = CAST( REPLICATE( 0x00, 128 ) AS varbinary(128) )
    SET CONTEXT_INFO @BinVar
    RETURN 0
END

DECLARE @UserGUIDBinary binary(16) --a guid is 16 bytes
SELECT @UserGUIDBinary = CAST(@UserGUID as binary(16))
SET CONTEXT_INFO @UserGUIDBinary


/* To load the guid back 
DECLARE @SavedUserGUID uniqueidentifier

SELECT @SavedUserGUID = CAST(context_info as uniqueidentifier)
FROM master.dbo.sysprocesses
WHERE spid = @@SPID

select @SavedUserGUID AS UserGUID
*/

नोट

  • स्टैकओवरफ़्लो कोड प्रारूप अधिकांश रिक्त पंक्तियों को हटा देता है - इसलिए स्वरूपण बेकार है
  • हम उपयोगकर्ताओं की तालिका का उपयोग करते हैं, एकीकृत सुरक्षा का नहीं
  • यह कोड एक सहमति के रूप में प्रदान किया गया है - हमारे डिजाइन चयन की किसी भी आलोचना की अनुमति नहीं है। शुद्धतावादी इस बात पर जोर दे सकते हैं कि सभी लॉगिंग कोड व्यावसायिक स्तर पर होने चाहिए - वे यहां आ सकते हैं और इसे हमारे लिए लिख सकते हैं/रख सकते हैं।
  • SQL सर्वर में ट्रिगर्स का उपयोग करके ब्लॉब्स को लॉग नहीं किया जा सकता है (ब्लॉब का कोई "पहले" संस्करण नहीं है - केवल वही है जो है)। टेक्स्ट और nText ब्लॉब्स हैं - जो नोट्स को या तो अनलॉग करने योग्य बनाता है, या उन्हें वर्कर (2000) बनाता है।
  • टैग कॉलम का उपयोग पंक्ति की पहचान करने के लिए एक मनमाना टेक्स्ट के रूप में किया जाता है (उदाहरण के लिए यदि कोई ग्राहक हटा दिया गया था, तो टैग ऑडिट लॉग टेबल में "जनरल मोटर्स नॉर्थ अमेरिका" दिखाएगा।
  • टैगगाइड का उपयोग पंक्ति के "पैरेंट" को इंगित करने के लिए किया जाता है। उदाहरण के लिए लॉगिंग InvoiceLineItems चालान शीर्षलेख . की ओर इशारा करता है . इस प्रकार किसी विशिष्ट चालान से संबंधित ऑडिट लॉग प्रविष्टियों की खोज करने वाला कोई भी व्यक्ति ऑडिट ट्रेल में लाइन आइटम के टैगगाइड द्वारा हटाए गए "लाइन आइटम" को ढूंढेगा।
  • कभी-कभी सार्थक स्ट्रिंग प्राप्त करने के लिए "OldValue" और "NewValue" मानों को उप-चयन के रूप में लिखा जाता है। यानी।"

    OldValue:{233d-ad34234..}नया मान:{883-sdf34...}

ऑडिट ट्रेल में इससे कम उपयोगी है:

OldValue: Daimler Chrysler
NewValue: Cerberus Capital Management

अंतिम नोट :हम जो करते हैं उसे न करने के लिए स्वतंत्र महसूस करें। यह हमारे लिए बहुत अच्छा है, लेकिन बाकी सभी लोग इसका इस्तेमाल न करने के लिए स्वतंत्र हैं।



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. मैक ओएस एक्स के लिए एसक्यूएल क्लाइंट जो एमएस एसक्यूएल सर्वर के साथ काम करता है

  2. मैं DBNull.Value के साथ एक नल स्ट्रिंग को स्पष्ट रूप से और जल्दी से कैसे माप सकता हूं?

  3. GUID के लिए SCOPE_IDENTITY ()?

  4. SQL सर्वर - क्या होता है जब किसी तालिका में एक पंक्ति अद्यतन की जाती है?

  5. साइन () SQL सर्वर में उदाहरण