Modern BI ve CRM sistemleri genellikle kullanıcı filtrelerini gerçekleştirmeyi gerektirir: tarih, cinsiyet, durum, etiketler gibi rastgele koşulları esnek bir şekilde birleştirmek önemlidir ve bunları SQL dilinde doğru şekilde kesiştirmek ve birleştirmek gerekir. Ortaya çıkan kod okunabilir, kolay değiştirilebilir ve beklenen sonucu vermelidir.
Geliştiriciler genellikle "anlık" olarak kullanıcı filtrelerinden oluşan birden fazla AND/OR ile WHERE oluşturur, bu da mantıksal hatalara ve bakımının zor olduğu sorgulara yol açar. Sorun, filtre değerlerinin mevcut olmayabileceği veya IN/EXISTS/LIKE ile birleştirilebileceği durumlarda daha da kötüleşir.
Dinamik filtreler için "değer verilmediğinde koşul ile OR (her zaman DOĞRU)" modeli uygundur:
SELECT * FROM users WHERE (status = @status OR @status IS NULL) AND (gender = @gender OR @gender IS NULL) AND (created >= @from_date OR @from_date IS NULL) AND (city IN (@cities) OR @cities IS NULL);
Ya da dinamik SQL ile:
DECLARE @sql NVARCHAR(MAX) = N'SELECT * FROM users WHERE 1=1'; IF @status IS NOT NULL SET @sql += N' AND status = @status'; IF @gender IS NOT NULL SET @sql += N' AND gender = @gender'; -- ... EXEC sp_executesql @sql, N'@status NVARCHAR(10),@gender NVARCHAR(10)', @status, @gender;
Temel Özellikler:
WHERE 1=1'i her yerde koşulların varlığını kontrol etmek yerine kullanabilir miyim?
Hayır, 1=1 yalnızca WHERE'yi birleştirmek için başlangıç koşuludur — filtreleri değiştirmez, yalnızca sorgu oluşturma kolaylığı için kullanılır.
IN () içine boş bir liste girdiğinde hangi sorunlar ortaya çıkabilir?
IN (NULL) veya IN () her zaman false döndürür ve boş bir set verir, hatta filtre olmamasına rağmen. Doğru çalışması için listenin boş olup olmadığını ayrı olarak kontrol etmek ve koşulu tamamen dışarıda bırakmak gerekir.
Bu tür yapılar indeks kullanımı ve performansı nasıl etkiler?
Eğer filtreler OR veya NULL kontrolleri ile uygulanırsa, birçok DBMS indeksi etkili bir şekilde kullanmayı bırakacak veya tüm tablonun taranmasını gerçekleştirecektir. Planlayıcının indeksi seçebilmesi için dinamik SQL veya parametreli sorgularla filtrelere yaklaşım uygulanmalıdır.
Klasik bir rapor 10 filtre ile, kod birçok OR ile WHERE oluşturuyor — birkaç filtrenin olmaması durumunda sonuç boş set veya çok büyük bir tarama ile dönebilir, sunucu üzerindeki yük kat kat artar.
Artılar:
Ayrı bir fonksiyon yalnızca belirtilen parametrelere dayalı filtreler oluşturur ve koşul grupları için yalnızca ayrı bir JOIN/FILTER dahil edilir. Where'de OR ve gereksiz NULL kontrolleri yoktur.
Artılar: