Tablodaki Satır Değişmiş mi ? (CHECKSUM ve timestamp)

SQL Server’da uygulamamız için kritik olan tablodaki bazı veya tüm alanların değişip değişmediğini öğrenmemiz gerektiğinde bunun için ya log, history gibi arşiv tabloları oluşturulur veya o satır değiştiği zaman o satır için tanımlı versiyon numarasını değiştiririz. Tarihçe tablolarını oluşturmamız hem değişiklik olup olmadığını hem de verilerin eski ve yeni değerlerini görmemize imkan tanır. Ancak değişiklik olup olmadığını anlamak için tarihçe tablosu ile ana tabloyu JOIN edip kolon seviyesinde fark olup olmadığına bakmamız gerekir. Bu da uğraştırıcı bir durum olduğu için sadece bu amaç için tarihçe tablosu oluşturmak mantıklı olmayabilir. SQL Server’in sunduğu CHECKSUM() fonksiyonu ve timestamp veri türü bu aşamada kolaylık sağmaktadır. Kontrol sayısı olarak türkçeleştirebileceğimiz CHECKSUM() fonksiyonu parametre olarak aldığı değer için bir hash değeri döndürür. Bu değer normal bir veri olabileceği gibi bir kolon veya kolonlar listesi de olabilir.

Örneğin aşağıdaki sorgu için -763255165 değeri döner.

SELECT CHECKSUM('MS SQL Server')

Bu fonksiyonu tablodaki satırların belli ve tüm kolonlarının değişip değişmediğini anlamak için kullanacağız. Bunun için yapmamız gereken şey bu fonksiyonu parametre olarak ilgili kolonları yazmak veya doğrudan “*” parametresini girmektir. Böyle o satır için bir hash değeri elde etmiş oluruz. Kolonlardan biri değiştiği zaman otomatik olarak bu değer de değişmiş olacaktır. Bu değeri kontrol ederek o satırın değişip değişmediğini anlayabiliriz. Urun tablosun RowNumber isimli bir alan ekliyorum. Ve bu alan üzerinde UrunAdi’na bağlı olmak üzere CHECKSUM() fonksiyonunu tanımlayacağız.

ALTER TABLE Urun ADD RowNumber AS CHECKSUM(UrunAdi);


Şeklinde görüleceği gibi 1 nolu ürün için 856465166 değeri üretilmiştir. Şimdi bu satırı güncelleyelim.

UPDATE Urun SET UrunAdi='U01' WHERE UrunId=1

Ardından tabloyu tekrar okuyalım. Güncelleme sornası 856465166 değeri -1020804159 olarak değişmiş oldu.

Bu mantıkla 2 tablonun benzer satırlarını kolayca bulabiliriz. Tabloların belli periyotlarla başka bir veritabanına taşıyorsak bu 2 kaynak arasında JOIN yapıp sadece kodu farklı olanlar MERGE edilebilir.

SELEC * FROM
	(SELECT CHECKSUM(*) chk1 FROM Table1) as T1
LEFT JOIN
	(SELECT CHECKSUM(*) chk1 FROM Table2) as T2
ON T1.KolonId=T2.KolonId 
WHERE T1.chk1 <> T1.chk1

CHECKSUM() fonksiyonuyla aynı mantığa sahip BINARY_CHECKSUM() içeriği binary olarak değerlendirir. Büyük küçük karakter hasassiyeti istenirse bu fonksiyon kullanılabilir.
Konuyla ilgili diğer ifade timestamp veri tipidir. İçerisinde zaman kavramı geçse de tarih bilgisini belirtmekle hiçbir ilgisi bulunmamaktadır. Nitekim SQL Server Books Online’da aşağıdaki cümle yazmaktadır.
The SQL Server timestamp data type has nothing to do with times or dates. SQL Server timestamps are binary numbers that indicate the relative sequence in which data modifications took place in a database. The timestamp data type was originally implemented to support the SQL Server recovery algorithms.
Bu veri tipini satırın değişip değişmediğini izlemek için kullanırız. Bu nedenle bazı kaynaklarda ROWVERSION olarak tanımlanır. Aşağıdaki gibi bir tablo oluşturalım.

CREATE TABLE tbTmStmp(
	SatirId int,
	AdiSoyadi varchar(10),
	SatirSurumNo timestamp,
	Tarih1 smalldatetime,
	Tarih2  datetime)

timestamp türündeki kolonu isim vermeyebiliriz. Bu durumda SQL Server otomatik timestamp ismini verecektir.

CREATE TABLE tbTmStmp(
	SatirId int,
	AdiSoyadi varchar(10),
	timestamp,
	Tarih1 smalldatetime,
	Tarih2  datetime)

Tabloya kayıt girelim. timestamp alanına herhangi bir değer girmiyoruz SQL Server o anki değeri kendisi set edecektir.

INSERT tbTmStmp(SatirId,AdiSoyadi,Tarih1,Tarih2)
VALUES(1,'Ahmet',GETDATE(),GETDATE())


Bu satırı güncelleyelim.

UPDATE tbTmStmp SET AdiSoyadi='Mehmet' WHERE SatirId=1

Tabloyu yeniden okuğumuzda Satır Sürüm No alanının 0×00000000000007D5 değerinden 0×00000000000007D6 değerine dönüştüğünü görürüz.
Tablo kayıt değişimleri ile ilgili kullanılan veri tiplerinden biri de UNIQUEIDENTIFIER türüdür. Bu da aynı şekilde TIMESTAMP gibi kullanılabilir. Fakat timestamp’ten farkı timestamp türü 8 byte iken uniqueidentifier türü 16 byte yer kaplar. timestamp, sistemin tarih bilgisine bağlı değildir. uniqueidentifier ise makinedeki MAC adresi ve tarih bilgisini referans alarak oluşur. uniqueidentifier’in en büyük avantajı dünyadaki hiçbir sistemde aynı değerin oluşmayacak olmasıdır.

Tablodaki Satır Değişmiş mi ? (CHECKSUM ve timestamp)” hakkında 3 yorum

  1. Murat Can

    Ahmet Bey ,
    Yazınızı dikkatle okudum.Kafama takılan bir senaryo oldu.o senaryonun bu mantıkla çözülüp çözülmeyeceğini merak ediyorum.
    Örneğin bir e-ticaret sitemiz var.Bir müşteri bir ürünü listeden seçip detay sayfasına girdi.Bu üründen stokta 1 tane var.Müşteri ürünü incelerken başka bir müşteri bu ürünü satın aldı.Böylece stok adedi sıfır oldu.Bunu biz ürünü inceleyen kullanıcının sayfasına yansıtmak istersek(Kullanıcı sadece sayfayı inceliyor.herhangi bir post işlemi olmadan) o ürünün ilk değerini alıp son değeriyle kıyaslayarak anlayabiliriz.Ancak burada kafama takılan, bir web sayfasında müşteri sayfada gezindiği sürede her sn de bir mi sorgu atıp kontrol etmeliyiz?Bu işin sonucunu kullanıcı tarafına yansıtmanın en iyi yöntemi nedir?
    Aslında kafama en çok takılan kısmı kullanıcı bir işlem yapmadan anlık olarak nasıl yansıtabileceğimiz?
    Konuyla ilgili düşüncelerinizi paylaşırsanız sevinirim.

    Murat Can

    Cevapla
    1. Uğur DEMİREL

      hocam signalR işinizi çözmezmi. ben de kontrol gereği bir işlemde sayfa yenilenmeden yapılan değişiklikleri müşteri bilgisayara yansıtmam gerekiyordu.signalR ile çözmüştüm

      Cevapla
  2. Ahmet Kaymaz Yazar

    Murat Can merhaba,

    Bu vb real-time web uygulamalarını yapabilmek için SignalR’ı incelemeni tavsiye ederim. Eğer doğrudan veri tabanını dinlemek isteniyorsa SqlDependency sınıfını da incelemekte fayda var. Hatta SqlDependency ile SignalR birlikte kullanılabilir.

    Cevapla

Murat Can için bir cevap yazın Cevabı iptal et

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir