ProgramlamaBackend geliştirici

SQL'de karmaşık iş anahtarları örneği ile verilerin benzersizliğini sağlamak için etkili bir kontrol mekanizması nasıl uygulanır, özellikle NULL değerlerine izin verildiğinde?

Hintsage yapay zeka asistanı ile mülakatları geçin

Cevap.

İlişkisel veritabanlarında benzersizlik sağlama görevi genellikle UNIQUE kısıtlamaları üzerindedir. Ancak iş pratiğinde, bazıları NULL olabilen alan kombinasyonları için benzersizlik gerektiği durumlar vardır (örneğin, email+telefonun benzersiz kombinasyonu, ancak telefon bilinmeyebilir).

Konu: SQL'de standart UNIQUE KISITLAMALARI, bir sütun NULL olduğunda benzersizliği garanti etmez; spesifikasyon bu tür değerleri birbirleriyle çelişiyor kabul eder.

Sorun: NULL içeren karmaşık anahtarlar için standart kısıtlamalar, tekrar eden kayıtlar oluşturur. Bu, özellikle veri bütünlüğü gerekiyorsa kritik öneme sahiptir: veri içe aktarma, göç, toplu güncellemeler sırasında.

Çözüm: Tüm değerleri (NULL da dahil) dikkate alan hesaplanan bir sütun kullanmak ve bu sütuna benzersizlik uygulamak ya da tetikleyici mantığı kullanmak.

Kod örneği:

ALTER TABLE my_table ADD computed_uniqueness AS ( ISNULL(email, '') + '#' + ISNULL(phone, '') ); CREATE UNIQUE INDEX idx_my_table_computed_uniqueness ON my_table(computed_uniqueness);

Ya da (NULL'lerin farklı sayıldığı ve ifadelerin indeks içinde olduğu PostgreSQL için):

CREATE UNIQUE INDEX idx_unique_email_phone ON my_table ((COALESCE(email, '##')),(COALESCE(phone, '##')));

Anahtar özellikler:

  • NULL ile kombinasyonlar için benzersizlik kuralının açık yönetimi.
  • Veri tabanı düzeyinde otomasyon ve destek sağlama imkanı.
  • Karmaşık ve değişken şemalar için destek.

Yanlış Sorular.

NULL değerini içeren sütunların bir kısmı için benzersizliği sağlamak amacıyla standart UNIQUE indeksi kullanmak mümkün müdür?

Hayır. ANSI SQL'e göre, UNIQUE indeksi, en az bir sütun NULL olduğunda birkaç satıra izin verir; çünkü NULL başka hiçbir değerle eşit sayılmaz, NULL dahil.

Bir ifade üzerinde benzersiz indeks kullanmak ile benzersizliği kontrol etmek için BEFORE INSERT tetikleyicisi kullanmak arasındaki fark nedir?

Benzersiz indeks, desteklenmesi daha kolay ve daha hızlıdır, ancak her zaman karmaşık iş kurallarını yerine getiremeyebilir (örneğin, istisnalar veya özel kombinasyonlar). Tetikleyici daha esnektir, fakat daha yavaş ve bakım için daha karmaşıktır.

Örnek:

CREATE OR REPLACE FUNCTION check_custom_unique() RETURNS TRIGGER AS $$ BEGIN IF EXISTS ( SELECT 1 FROM my_table WHERE COALESCE(NEW.email, '##') = COALESCE(email, '##') AND COALESCE(NEW.phone, '##') = COALESCE(phone, '##') ) THEN RAISE EXCEPTION 'Duplicate found'; END IF; RETURN NEW; END; $$ LANGUAGE plpgsql; CREATE TRIGGER trg_custom_unique BEFORE INSERT OR UPDATE ON my_table FOR EACH ROW EXECUTE FUNCTION check_custom_unique();

Uygulama düzeyinde benzersizliği sağlamak için SELECT'te DISTINCT kullanılabilir mi?

Evet, ancak yalnızca seçim için — bu, veri değişiklikleri sırasında tekrarları önlemez ve tablo düzeyinde kısıtlamaların yerini almaz.

Tipik hatalar ve anti-paternler

  • Benzersiz kısıtlamaları, anahtarın NULL olabilen kombinasyonlarla çalıştığı yerlerde kullanmaya çalışmak.
  • Benzersizliği yalnızca uygulama düzeyinde kontrol etmek (veri tabanını atlayarak).
  • Açık indeksler olmadan tetikleyicilerin fazla karmaşık hale gelmesi — performans kaybı.

Gerçek hayattan örnek

Olumsuz durum

Şirket, benzersizliği email+telefon aracılığıyla UNIQUE(email, phone) ile uygular. Veritabanında, telefon=NULL olduğunda email'e göre tekrar eden kayıtlar oluşur.

Artıları:

  • Uygulama kolaylığı.

Eksileri:

  • Bütünlük kaybı, tekrarlar.
  • Analitiklerde izlenmesi zor, gizli hatalar.

Olumlu durum

Hesaplanan bir sütun (COALESCE(email, '##') + '#' + COALESCE(phone, '')), üzerine benzersiz indeks uygulanır.

Artıları:

  • Veri tabanı tekrarları hariç tutar, her işlem (UPDATE, INSERT) anında işlenir.

Eksileri:

  • Yeniden indeksleme, büyük veri kümelerinde zaman alabilir.
  • İndeks boyutlarını etkiler.