Sql & Veritabanı İle Uygulamalar İçin Veri Kayıt Kısıtlama Kuralları Nasıl Yapılır?

Sql & Veritabanı İle Uygulamalar İçin Veri Kayıt Kısıtlama Kuralları Nasıl Yapılır?
Sql & Veritabanı İle Uygulamalar İçin Veri Kayıt Kısıtlama Kuralları Nasıl Yapılır?

Ön Hazırlık ve Gereksinimler

Bu teknik rehberi takip edebilmek için temel düzeyde SQL bilgisine ve bir veritabanı yönetim sistemine (PostgreSQL, MySQL veya SQL Server) sahip olmanız gerekir. Örneklerimiz, endüstri standardı olan ANSI SQL sözdizimine dayanmaktadır.

  • Veritabanı Motoru: PostgreSQL 16+ veya MySQL 8.4+ sürümü önerilir.
  • Araçlar: DBeaver, pgAdmin veya komut satırı arayüzü (CLI).
  • Bilgi Seviyesi: Tablo oluşturma (CREATE TABLE) ve kısıtlama (CONSTRAINT) mantığına aşinalık.

Temel Kısıtlamalar: NOT NULL ve UNIQUE Kullanımı

Veri kayıt kısıtlama kuralları arasında en sık kullanılanlar, sütunların boş geçilemez (NOT NULL) ve benzersiz (UNIQUE) olmasıdır. Bu kısıtlamalar, veritabanına hatalı kayıt girişini daha ilk aşamada reddeder.

Aşağıdaki örnekte, bir kullanıcı tablosu oluştururken e-posta adresinin benzersiz olması ve kullanıcı adının boş bırakılamaması kuralını tanımlıyoruz:

CREATE TABLE kullanicilar (
    id SERIAL PRIMARY KEY,
    kullanici_adi VARCHAR(50) NOT NULL,
    eposta VARCHAR(100) UNIQUE NOT NULL,
    kayit_tarihi TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

Bu kod bloğunda NOT NULL ifadesi, ilgili sütuna veri girilmeden kayıt eklenmesini engeller. UNIQUE ise aynı e-posta adresiyle ikinci bir kayıt açılmasını veritabanı seviyesinde yasaklar.

CHECK Kısıtlaması ile Mantıksal Kurallar Koyma

CHECK kısıtlaması, bir sütuna girilen verinin belirli bir mantıksal koşulu sağlamasını zorunlu kılar. Örneğin, bir ürünün fiyatının sıfırdan küçük olamayacağını veya bir yaş sınırının belirli bir aralıkta olması gerektiğini bu yöntemle garanti altına alırsınız.

Aşağıdaki örnekte, ürün fiyatının her zaman pozitif olması için bir kısıtlama ekliyoruz:

ALTER TABLE urunler
ADD CONSTRAINT chk_fiyat_pozitif 
CHECK (fiyat > 0);

Bu kural, uygulama katmanında bir hata olsa dahi, veritabanına negatif bir fiyat değerinin yazılmasını imkansız hale getirir. Test etmek için INSERT INTO urunler (fiyat) VALUES (-10); komutunu çalıştırdığınızda veritabanı "Check constraint violation" hatası dönecektir.

Foreign Key (Yabancı Anahtar) ile İlişkisel Bütünlük

Veritabanı uygulamalarında tablolar arası ilişkileri korumak, veri kayıt kısıtlama kuralları arasında en önemlisidir. FOREIGN KEY, bir tablodaki verinin başka bir tablodaki geçerli bir kayda referans vermesini sağlar.

Aşağıdaki örnekte, siparişler tablosunun sadece geçerli bir kullanıcıya bağlanabileceğini tanımlıyoruz:

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

ON DELETE CASCADE ifadesi, bir kullanıcı silindiğinde ona ait tüm siparişlerin de otomatik olarak temizlenmesini sağlar. Bu, veritabanınızda "yetim kayıtlar" (orphan records) oluşmasını engeller.

Veri Kısıtlama Yöntemlerinin Karşılaştırması

Aşağıdaki tablo, farklı kısıtlama yöntemlerinin kullanım amaçlarını ve avantajlarını özetlemektedir:

Kısıtlama Türü Amacı Avantajı
NOT NULL Boş veri girişini engeller Veri bütünlüğü sağlar
UNIQUE Tekrarlanan veriyi engeller Mükerrer kaydı önler
CHECK Mantıksal aralıkları denetler Veri kalitesini korur
FOREIGN KEY İlişkisel tutarlılığı sağlar İlişkili veriyi kontrol eder

Güvenlik Uyarısı: Veritabanı kısıtlamaları, uygulamanızın son savunma hattıdır. SQL Injection saldırılarına karşı korunmak için her zaman parametreli sorgular (prepared statements) kullanın. Veritabanı kısıtlamaları, uygulama katmanındaki güvenlik önlemlerinin yerini tutmaz, onları tamamlar.

Trigger (Tetikleyici) ile Gelişmiş Kısıtlamalar

Bazen standart kısıtlamalar karmaşık iş mantığını karşılamaya yetmez. Bu durumlarda TRIGGER kullanarak kayıt anında daha detaylı kontroller yapabilirsiniz. Örneğin, bir kullanıcının günde en fazla 3 sipariş vermesini kısıtlamak isteyebilirsiniz.

CREATE OR REPLACE FUNCTION siparis_limiti_kontrol()
RETURNS TRIGGER AS $$
BEGIN
    IF (SELECT COUNT(*) FROM siparisler WHERE kullanici_id = NEW.kullanici_id AND tarih = CURRENT_DATE) >= 3 THEN
        RAISE EXCEPTION 'Günlük sipariş limitine ulaşıldı.';
    END IF;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER trg_siparis_limiti
BEFORE INSERT ON siparisler
FOR EACH ROW EXECUTE FUNCTION siparis_limiti_kontrol();

Bu tetikleyici, her INSERT işleminden önce çalışır ve belirtilen mantıksal koşulu kontrol eder. Eğer koşul sağlanmıyorsa, veritabanı işlemi iptal eder.

Sıkça Sorulan Sorular

Veritabanı kısıtlamaları performansı düşürür mü?

Küçük ölçekli kısıtlamalar (NOT NULL, UNIQUE) performans üzerinde ihmal edilebilir bir etkiye sahiptir. Ancak çok karmaşık tetikleyiciler (triggers) yoğun yazma işlemlerinde gecikmeye neden olabilir; bu yüzden tetikleyicileri dikkatli kullanmalısınız.

Uygulama katmanındaki kontroller yeterli değil mi?

Uygulama katmanındaki kontroller kullanıcı deneyimi için gereklidir, ancak veritabanı kısıtlamaları verinin doğruluğunu garanti eden tek "gerçek" kaynaktır. Doğrudan veritabanına erişen diğer servisler için de bu kurallar geçerli kalır.

Kısıtlamaları test ederken nelere dikkat etmeliyim?

Kısıtlamaları test ederken "mutlu yol" (geçerli veriler) ve "hata yolu" (geçersiz veriler) senaryolarını ayrı ayrı çalıştırmalısınız. Hata durumunda veritabanının döndürdüğü hata mesajlarını uygulamanızda yakalayıp kullanıcıya anlamlı bir şekilde göstermelisiniz.

Var olan bir tabloya kısıtlama ekleyebilir miyim?

Evet, ALTER TABLE komutu ile tabloya sonradan CHECK veya FOREIGN KEY kısıtlamaları ekleyebilirsiniz. Ancak mevcut verilerin kısıtlamaya uygun olduğundan emin olmalısınız, aksi takdirde kısıtlama ekleme işlemi hata verecektir.

Hangi durumlarda kısıtlama kullanmamalıyım?

Sık değişen iş mantıkları için veritabanı kısıtlamaları yerine uygulama katmanı kontrolleri tercih edilebilir, çünkü veritabanı şemasını değiştirmek uygulama kodunu değiştirmekten daha zahmetli olabilir.

Veri Kısıtlama Hatalarını Yönetme ve Debugging Stratejileri

Veritabanı kısıtlamaları (constraints) devreye girdiğinde, uygulama katmanında genellikle SQLException veya benzeri bir hata fırlatılır. Bu hataları kullanıcıya anlamlı bir mesaj olarak döndürmek, hem kullanıcı deneyimi hem de sistemin güvenliği için kritiktir. Hatalı veri girişlerini izlemek ve kök nedeni bulmak için şu adımları izleyebilirsiniz:

Hata Kodlarını Yakalama ve Anlamlandırma

Veritabanı motorları, ihlal edilen kısıtlamalar için özel hata kodları üretir. Örneğin, PostgreSQL'de 23505 hata kodu unique_violation durumunu temsil eder. Uygulamanızda bu kodları yakalayarak kullanıcıya "Bu e-posta zaten kayıtlı" gibi özel mesajlar gösterebilirsiniz.

-- Örnek: Hata yakalama mantığı (Pseudo-code)
TRY {
    INSERT INTO users (email) VALUES ('test@example.com');
} CATCH (DatabaseException e) {
    IF (e.getErrorCode() == '23505') {
        PRINT "Bu e-posta adresi sistemimizde zaten mevcut.";
    }
}

Kısıtlama İhlallerini Loglama

Kısıtlama ihlalleri, genellikle uygulamanızdaki bir mantık hatasına veya kötü niyetli bir veri girişine işaret eder. Bu nedenle, veritabanı seviyesinde reddedilen her işlemi loglamak, sistemin zayıf noktalarını tespit etmenize yardımcı olur.

Karmaşık İş Mantığı İçin "Constraint Validation" Senaryosu

Bazen kısıtlamalar tek bir sütunla sınırlı kalmaz; birden fazla tablonun veya karmaşık iş kurallarının birleşimi gerekebilir. Örneğin, bir "E-Ticaret" sisteminde, bir kullanıcının aynı anda sadece bir "aktif" sepeti olabileceğini garanti etmek isteyebilirsiniz.

Bu tür senaryolarda standart kısıtlamalar yetersiz kalabilir. Bunun yerine, Partial Unique Index (Kısmi Benzersiz İndeks) kullanarak veritabanı seviyesinde kesinlik sağlayabilirsiniz:

-- Sadece 'active' durumu 'true' olan sepetler için benzersizlik kuralı
CREATE UNIQUE INDEX idx_unique_active_cart 
ON carts (user_id) 
WHERE status = 'active';

Bu yöntem, status = 'active' olan kayıtların user_id bazında benzersiz olmasını zorunlu kılar. Ancak, status = 'completed' veya status = 'cancelled' olan kayıtlar için bu kısıtlama devre dışı kalır. Bu sayede, veritabanı seviyesinde performansı düşürmeden iş mantığınızı korumuş olursunuz.

İleri Düzey İpuçları

  • Deferred Constraints: Eğer karmaşık işlemlerinizde kısıtlamaların işlem (transaction) sonunda kontrol edilmesini istiyorsanız DEFERRABLE özelliğini kullanın. Bu, döngüsel bağımlılıkları olan tablolarda veri girişi yapmanızı sağlar.
  • Constraint İsimlendirme: Kısıtlamalarınıza mutlaka anlamlı isimler verin (Örn: fk_order_customer). Hata mesajlarında sistem tarafından atanan rastgele isimler yerine kendi tanımladığınız isimleri görmek, hata ayıklamayı %50 hızlandırır.
  • Test Odaklı Geliştirme: Kısıtlamalarınızı "Unit Test" seviyesinde test edin. Hatalı veri gönderildiğinde veritabanının reddettiğini doğrulayan testler yazmak, gelecekteki şema değişikliklerinde sistemin kırılmasını önler.
Profesyonel Not: Veritabanı kısıtlamaları, uygulamanızın son savunma hattıdır. Asla sadece uygulama katmanındaki validasyonlara güvenmeyin; veritabanı her zaman "doğru" olanın tek kaynağı (Single Source of Truth) kalmalıdır.

Sonuç

Sql & Veritabanı ile uygulamalar için veri kayıt kısıtlama kuralları, verinizin uzun vadeli sağlığı için vazgeçilmezdir. NOT NULL, UNIQUE, CHECK ve FOREIGN KEY gibi araçları kullanarak uygulamanızın temelini sağlamlaştırabilirsiniz. Unutmayın ki, veritabanı seviyesinde alınan önlemler, uygulamanızı dış etkenlerden ve hatalı veri girişlerinden koruyan en güçlü kalkanınızdır.

Bir sonraki adım olarak, veritabanı indeksleme (indexing) stratejilerini inceleyerek kısıtlamalarınızın performansını nasıl optimize edebileceğinizi öğrenebilirsiniz. İyi kodlamalar dilerim.

Sorumluluk Reddi: Bu rehberde yer alan SQL kodları genel eğitim amaçlıdır. Üretim ortamında (production) herhangi bir şema değişikliği yapmadan önce veritabanınızı yedeklemeniz ve değişiklikleri önce geliştirme/test ortamlarında doğrulamanız şiddetle önerilir.

Bu yazıya tepkinizi paylaşın:
Emre Çelik

Verimlilik ve zaman yönetimi üzerine odaklanan bir yazarım. Günlük hayatı optimize eden ipuçları ve iş akışı optimizasyonu konularında içerikler üretiyorum.

Yorumlar (0)

Yorum Yaz