Sql & Veritabanı İle Uygulamalar İçin Veri Bütünlüğü Doğrulama Nasıl Yapılır?

Gereksinimler ve Ortam Kurulumu

Veri bütünlüğü uygulamalarını hayata geçirmek için güncel bir veritabanı yönetim sistemine ihtiyacınız vardır. Bu rehberde PostgreSQL 17 ve üzeri sürümler baz alınmıştır, ancak kullanılan SQL standartları MySQL 9.0 ve SQL Server 2025 ile büyük oranda uyumludur.

  • PostgreSQL 17 veya güncel bir RDBMS sunucusu.
  • SQL sorgularını çalıştırmak için DBeaver veya pgAdmin gibi bir veritabanı yönetim aracı.
  • Uygulama katmanı için modern bir programlama dili (Örn: Python, PHP veya Node.js).

Tablo Seviyesinde Kısıtlamalar (Constraints) Kullanımı

Veri bütünlüğünü sağlamanın en etkili yolu, veritabanı şeması oluşturulurken kısıtlamaları doğru tanımlamaktır. Kısıtlamalar, veritabanına eklenen verinin belirli kurallara uymasını zorunlu kılar.

Aşağıdaki örnekte, bir kullanıcı tablosu oluştururken NOT NULL ve CHECK kısıtlamalarını nasıl kullanacağımızı görebilirsiniz.

CREATE TABLE kullanicilar (
    id SERIAL PRIMARY KEY,
    kullanici_adi VARCHAR(50) NOT NULL,
    yas INT CHECK (yas >= 18),
    eposta VARCHAR(100) UNIQUE NOT NULL
);

Bu kodda yas sütununa 18'den küçük bir değer girilmeye çalışıldığında veritabanı hata döndürecektir. UNIQUE kısıtlaması ise aynı e-posta adresiyle birden fazla kayıt oluşturulmasını engeller.

İlişkisel Bütünlük: Foreign Key ve Cascade İşlemleri

Tablolar arasındaki ilişkileri korumak için FOREIGN KEY (yabancı anahtar) kullanılır. Bu, bir tablodaki verinin başka bir tablodaki geçerli bir kayda bağlı olmasını sağlar. ON DELETE CASCADE kullanımı, ana kayıt silindiğinde ona bağlı alt kayıtların da otomatik silinmesini sağlar.

CREATE TABLE siparisler (
    siparis_id SERIAL PRIMARY KEY,
    kullanici_id INT REFERENCES kullanicilar(id) ON DELETE CASCADE,
    tutar DECIMAL(10, 2) NOT NULL
);

Bu yapı, veritabanında "yetim kayıt" (orphan record) oluşmasını engeller. Eğer bir kullanıcı silinirse, o kullanıcıya ait tüm siparişler de veritabanı tarafından otomatik olarak temizlenir.

Veri Bütünlüğü Yöntemlerinin Karşılaştırılması

Yöntem Avantajı Dezavantajı
Check Constraint Hızlı ve basit doğrulama Karmaşık mantıkta zorlanır
Foreign Key İlişkisel bütünlüğü garantiler Performans maliyeti olabilir
Trigger Çok karmaşık kuralları işler Bakımı ve debug etmesi zordur

Trigger (Tetikleyici) ile Karmaşık Doğrulamalar

Bazen standart kısıtlamalar yeterli olmaz. Örneğin, bir stok güncellemesi sırasında stok miktarının negatif değer almasını engellemek için tetikleyiciler kullanılır. Tetikleyiciler, belirli bir olay (INSERT, UPDATE) gerçekleştiğinde otomatik çalışan fonksiyonlardır.

CREATE OR REPLACE FUNCTION stok_kontrol_fonksiyonu()
RETURNS TRIGGER AS $$
BEGIN
    IF NEW.stok_miktari < 0 THEN
        RAISE EXCEPTION 'Stok miktarı negatif olamaz!';
    END IF;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER stok_kontrol_trigger
BEFORE UPDATE ON urunler
FOR EACH ROW EXECUTE FUNCTION stok_kontrol_fonksiyonu();

Bu tetikleyici, urunler tablosundaki her güncelleme öncesinde stok miktarını kontrol eder ve kural ihlalinde işlemi durdurur.

Uygulama Katmanında Veri Doğrulama ve SQL Injection Koruması

Veritabanı kısıtlamaları son savunma hattıdır; ancak veriyi uygulamadan göndermeden önce de doğrulamalısınız. SQL Injection saldırılarını önlemek için mutlaka "Prepared Statements" (Hazırlanmış İfadeler) kullanın.

-- Güvenli olmayan yöntem (ASLA KULLANMAYIN)
-- "SELECT * FROM users WHERE id = " + kullanici_id;

-- Güvenli yöntem (Prepared Statement)
PREPARE get_user (int) AS
SELECT * FROM kullanicilar WHERE id = $1;

EXECUTE get_user(10);

Parametreli sorgular, kullanıcıdan gelen verinin SQL komutu olarak değil, sadece veri olarak işlenmesini sağlar. Bu, en yaygın güvenlik açıklarından birini kökten çözer.

Kritik Uyarı: Veritabanı bütünlüğü için sadece uygulama katmanına güvenmeyin. Uygulama kodunuzdaki bir hata, veritabanı kısıtlamalarını devre dışı bırakamaz. Ancak veritabanı kısıtlamaları, uygulama katmanındaki hatalara karşı verinizi koruyan en güçlü savunmadır.

Sıkça Sorulan Sorular

Veritabanı kısıtlamaları performans kaybına neden olur mu?

Küçük ölçekli uygulamalarda ihmal edilebilir düzeydedir. Büyük ölçekli sistemlerde ise doğru indeksleme ile bu kısıtlamaların performansa etkisi optimize edilebilir.

Trigger kullanmak yerine uygulama kodunda kontrol yapsam olmaz mı?

Uygulama kodunda yapılan kontroller, veritabanına doğrudan erişen başka bir araç veya script kullanıldığında geçersiz kalır. Veritabanı seviyesindeki kısıtlamalar, verinin kaynağını korur.

NULL değerler veri bütünlüğünü nasıl etkiler?

NOT NULL kısıtlaması kullanılmayan sütunlarda eksik veri oluşabilir. Bu durum, raporlama ve analiz işlemlerinde beklenmedik hatalara yol açar.

Foreign Key silinirken neden hata alıyorum?

İlgili tabloda o anahtara bağlı veriler olduğu için veritabanı tutarlılığı korumak adına silme işlemine izin vermez. ON DELETE CASCADE veya ON DELETE SET NULL kullanarak bu davranışı yönetebilirsiniz.

Veri bütünlüğü için en iyi pratik nedir?

Veritabanı şemasını kısıtlamalarla (PK, FK, CHECK, NOT NULL) mümkün olduğunca sıkı tutmak ve uygulama tarafında da veriyi doğrulamak en güvenli yaklaşımdır.

Güvenlik Sorumluluk Reddi: Bu makalede paylaşılan kod örnekleri eğitim amaçlıdır. Üretim ortamına almadan önce kendi veri yapınıza uygun güvenlik testlerini yapmalı ve veritabanı kullanıcı yetkilerini (Least Privilege Principle) sınırlandırmalısınız.

Veri Bütünlüğü İçin Stratejik Hata Ayıklama ve Loglama

Veri bütünlüğü kurallarını uygularken, sistemin neden hata verdiğini anlamak geliştirici deneyimi için kritiktir. SQL kısıtlamaları (constraints) ihlal edildiğinde veritabanı motoru genellikle genel bir hata kodu döner. Bu durumun önüne geçmek ve kullanıcıya anlamlı mesajlar iletmek için veritabanı seviyesinde hata yakalama mekanizmaları oluşturmalısınız.

Özel Hata Mesajları ve İstisna Yönetimi

PostgreSQL veya SQL Server gibi sistemlerde, kısıtlamalara özel hata mesajları atayarak uygulama tarafındaki hata ayıklama sürecini hızlandırabilirsiniz. Aşağıdaki örnekte, bir yaş kısıtlaması ihlal edildiğinde veritabanının spesifik bir hata mesajı dönmesi sağlanmıştır:

-- PostgreSQL örneği: Hata mesajını özelleştirme
ALTER TABLE Kullanicilar 
ADD CONSTRAINT chk_yas_siniri 
CHECK (yas >= 18);

-- Uygulama katmanında hata yakalama (Python/Psycopg2 örneği)
try:
    cursor.execute("INSERT INTO Kullanicilar (yas) VALUES (15)")
except psycopg2.errors.CheckViolation:
    print("Hata: Kullanıcı 18 yaşından küçük olamaz.")

Hata ayıklama sürecinde, kısıtlamaların hangi satırda ve hangi değerle çakıştığını belirlemek için pg_stat_statements veya SQL Profiler gibi araçları kullanarak "Constraint Violation" loglarını izlemeniz önerilir.

Veri Bütünlüğü Testleri İçin Otomasyon Stratejileri

Veritabanı şemanızdaki kısıtlamaların beklendiği gibi çalıştığını doğrulamak için "Unit Testing for Database" yaklaşımını benimsemelisiniz. Veritabanı testleri, uygulama kodundan bağımsız olarak kısıtlamaların geçerliliğini doğrular.

Test Senaryosu: Negatif Testler

Negatif testler, veritabanına "yanlış" verinin girmesini engellemek için tasarlanır. Bir test senaryosunda, kısıtlamaların veriyi reddedip reddetmediğini şu şekilde test edebilirsiniz:

  1. Hazırlık: Boş bir test tablosu oluşturun.
  2. Eylem: Kısıtlamayı ihlal eden bir veri seti gönderin.
  3. Doğrulama: Veritabanının SQLSTATE hata kodunun 23514 (Check Violation) olduğunu onaylayın.
-- Test tablosu oluşturma
CREATE TABLE test_urunler (
    fiyat DECIMAL CHECK (fiyat > 0)
);

-- Test sorgusu
BEGIN;
SAVEPOINT test_noktasi;
INSERT INTO test_urunler VALUES (-10); -- Bu satır hata vermeli
-- Eğer hata alınıyorsa test başarılıdır
ROLLBACK TO SAVEPOINT test_noktasi;
COMMIT;

Deployment Öncesi Bütünlük Kontrolleri

Canlı ortama (production) geçmeden önce, mevcut verilerinizin yeni eklediğiniz kısıtlamalarla uyumlu olup olmadığını kontrol etmelisiniz. Eğer halihazırda veritabanında hatalı veriler varsa, ALTER TABLE komutu başarısız olacaktır. Bu durumu yönetmek için NOT VALID anahtar kelimesini kullanabilirsiniz:

-- Mevcut verileri bozmadan kısıtlamayı ekle
ALTER TABLE Siparisler 
ADD CONSTRAINT fk_musteri_id 
FOREIGN KEY (musteri_id) REFERENCES Musteriler(id) NOT VALID;

-- Daha sonra verileri temizleyip kısıtlamayı doğrula
ALTER TABLE Siparisler VALIDATE CONSTRAINT fk_musteri_id;
Profesyonel İpucu: Büyük ölçekli veritabanlarında VALIDATE işlemi tabloyu kilitleyebilir. Bu nedenle, yoğun saatler dışında veya "Lock Timeout" sürelerini optimize ederek bu işlemleri gerçekleştirin.

Sonuç

Sql & veritabanı ile uygulamalar için veri bütünlüğü doğrulama süreci, sadece bir kodlama alışkanlığı değil, bir sistem mimarisi disiplinidir. Bu rehberde öğrendiğiniz CHECK, FOREIGN KEY, TRIGGER ve PREPARED STATEMENTS kullanımı, veritabanınızın yıllarca tutarlı ve güvenli kalmasını sağlayacaktır. Bir sonraki adım olarak, veritabanı indeksleme stratejilerini ve bu kısıtlamaların indeksleme ile olan ilişkisini incelemenizi öneririm.

Bu yazıya tepkinizi paylaşın:
Zeynep Kaya

Ev yönetimi ve kendin yap (DIY) projeleri konusunda uzmanlaşmış bir içerik üreticisiyim. Detaylı rehberler hazırlayarak okuyucuların evdeki küçük sorunları profesyonel yardıma gerek duymadan çözmelerini sağlıyorum.

Yorumlar (0)

Yorum Yaz