MS SQL veritabanında logging naısl yapılır.

MS SQL Server veritabanı ve SQL komutlarıyla ilgli sorularınızı sorabilirsiniz. Delphi tarafındaki sorularınızı lütfen Programlama forumunda sorunuz.
Cevapla
Kullanıcı avatarı
softdestek
Üye
Mesajlar: 155
Kayıt: 17 Eyl 2010 03:53

MS SQL veritabanında logging naısl yapılır.

Mesaj gönderen softdestek »

Veritabanında bulunan bazı tablolarımda logging yapmam gerekiyor. Örnek vermek gerekirse fiyat diye bir kolonum var bu fiyat kolonu değiştirilirse ne zaman değişti?Eski değeri neydi ?Yeni değeri ne? bu tür bilgiler ve eğer tablodan bir satır silinirse ne zaman silindi gibi bilgileri nasıl görebiliriz..

MS SQL TRACKING işlemi var bunununla sanırım belli bir güne kadar değişiklikleri takip edebiliyoruz..

Bu konuda googlada araştırma yapınca bu kavramı buldum..

Örnek bir tabloda logging işlemi gösteren bir çalışmayı bura da paylaşabilirseniz sevirinirim.
Yaptığım araştırma sonucu internette bulabildiğim en iyi örnek bu
http://weblogs.asp.net/jongalloway/addi ... r-database
Fakat bu örnek tablonun benzerini oluşturuyor bir field bile değişse kocaman bir satır şeklinde log tablosuna tüm field leri yazıyor.

İstediğim şey sadece değişen tablo ve ve değişen field değerlerini görmek..
Kısacası bu konuyla ilgili paylaşım yapabilirseniz sevinirim.
Sitedeki bununla ilgili konuları inceledim.Fakat istediğim gibi bir çözüm göremedim.
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4740
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Re: MS SQL veritabanında logging naısl yapılır.

Mesaj gönderen mrmarman »

Merhaba.
Ben olsam nasıl yapardım,
(1) bir LOG tablosu create ederdim.
(2) bu tabloda ( hepsi string olacak şekilde ) aşağıdaki FIELD tanımlamalarını yapardım.
1 TabloAdi, 2 FieldAdi, 3 DegisiklikTipi, 4 EskiDeger, 5 YeniDeger, 6 DegisiklikTar, 7 DegistirenKullanici
(3a) Sadece kullanıcı tarafından değişiklik yapılıyor da yapılan değişiklik Trigger'lar ile başka tabloara etki etmiyorsa !!!
. .* - Logla( ) isminde yukarıdaki FIELD tiplerine ilişkin içeriği koyup INSERT edecek (sadece INSERT veya SELECT INTO gerekiyor zaten) procedure hazırladım.
. .* - Kullanıcının KAYDET veya GÜNCELLE butonunun altına bu Logla() procedure'ünü koyar işini yapmasını sağlardım.
(3b) Kullanıcı tarafından değişiklik yapılıyor iken üstüne üstlük bir de bu yapılan değişiklik Trigger'lar ile başka tabloara etki ediyorsa !!!
. .* - Yukarıdaki logla kısmı yeterli ise (yani trigger ile tetiklenen yerlerin eski değerleri gereksiz ise) aynı şekilde yapardım.
. .* - TRIGGER eski değerlerini de logla kısmında kullanmak üzere önce bir değişken grubuna kayıt öncesi yedekler ( bir type tanımı gruplamak için idealdir ) POST sonrası da bunların yine parametre olarak geçeceğimiz Logla procedure üzerinden kayıt altına alınmasını sağlardım.

Şimdilik bu kadar, gelişmeler için konuşulabilir.
Resim
Resim ....Resim
Kullanıcı avatarı
softdestek
Üye
Mesajlar: 155
Kayıt: 17 Eyl 2010 03:53

Re: MS SQL veritabanında logging naısl yapılır.

Mesaj gönderen softdestek »

Ben örnek olması açısından aşağıdaki gibi bir örnek birt table guest oluşturdum.

Kod: Tümünü seç

USE [DENEME]
GO

/****** Object:  Table [dbo].[GUESTS]    Script Date: 04.07.2015 17:15:51 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

SET ANSI_PADDING ON
GO

CREATE TABLE [dbo].[GUESTS](
	[GUEST_ID] [int] IDENTITY(1,1) NOT NULL,
	[GUEST_NAME] [varchar](50) NULL,
	[GUEST_SURNAME] [varchar](50) NULL,
	[ADRESS] [varchar](100) NULL,
	[CITY] [varchar](50) NULL,
	[CITY_CODE] [varchar](10) NULL,
	[COUNTRY] [varchar](50) NULL,
	[STATUS] [varchar](20) NULL,
	[COMMENT] [nvarchar](max) NULL,
PRIMARY KEY CLUSTERED 
(
	[GUEST_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] TEXTIMAGE_ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO
Bu table için de aşağıdaki gibi bir triger oluşturdum...

Kod: Tümünü seç

USE [DENEME]
GO
/****** Object:  Trigger [dbo].[iudt_AutoAuditChanges]    Script Date: 04.07.2015 17:17:15 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[iudt_AutoAuditChanges] 
   ON  [dbo].[GUESTS]
   AFTER INSERT,DELETE,UPDATE
AS 
BEGIN
    SET NOCOUNT ON;

    Declare @v_AuditID bigint

    IF OBJECT_ID('dbo.AutoAudit','U') IS NULL BEGIN
        CREATE TABLE [dbo].[AutoAudit]
        (   [AuditID] bigint identity,
            [AuditDate] DateTime,
            [AuditUserName] varchar(128),
            [TableName] varchar(128) NULL,
            [OldContent] XML NULL,
            [NewContent] XML NULL
        )

        ALTER TABLE dbo.AutoAudit ADD CONSTRAINT
        PK_AutoAudit PRIMARY KEY CLUSTERED 
        (
            [AuditID]
        ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]

        CREATE NONCLUSTERED INDEX [idx_AutoAudit_TableName_AuditDate] ON [dbo].[AutoAudit] 
        (   [TableName] ASC,
            [AuditDate] ASC
        )WITH (STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
    END

    Select * Into #AuditDeleted from deleted
    Select * Into #AuditInserted from inserted

    While (Select COUNT(*) from #AuditDeleted) > 0 OR (Select COUNT(*) from #AuditInserted) > 0
    Begin

        INSERT INTO [dbo].[AutoAudit]
            ( [AuditDate], [AuditUserName], [TableName], [OldContent], [NewContent])
        SELECT 
            GETDATE(),
            SUSER_NAME(),
            [TableName]=object_name([parent_obj]),
            [OldContent]=CAST((SELECT TOP 1 * FROM #AuditDeleted D FOR XML RAW) AS xml),
            [NewContent]=CAST((SELECT TOP 1 * FROM #AuditInserted I FOR XML RAW) AS xml)
        FROM sysobjects 
        WHERE
            [xtype] = 'tr' 
            and [name] = OBJECT_NAME(@@PROCID)

        Set @v_AuditID = SCOPE_IDENTITY()

        Delete from AutoAudit
        Where AuditID = @v_AuditID
            AND Convert(varchar(max),oldContent) = Convert(varchar(max),NewContent)

        Delete top(1) from #AuditDeleted
        Delete top(1) from #AuditInserted

    End
END

Bu triger guest tablosunda olan tüm değişiklikleri AutoAudit tablosuna xml olarak yazıyor..

<row GUEST_ID="5" GUEST_NAME="GÖKHAN" GUEST_SURNAME="ÇEVİK" />

<row GUEST_ID="5" GUEST_NAME="GÖKHAN" GUEST_SURNAME="ÇEVİK21" />


Resim

Ben daha önce firebird veritabanı kullanırken aşağıdaki gibi log tutmuştum.Fakat kayıt sayısı artacağı için logu fieldler tanımlayarak tutmak yerine
xml olarak tutmak daha mı mantıklı arkadaşlar ne dersiniz?

Resim
Cevapla