SQL önerisi

Stored procedure(SP) yazarken, normal durumlarda IF-ENDIF, CASE gibi sorgular ile kuracağınız karar verme yapılarına seçenek olabilecek bir başka çözüm ise OR ile yapılacak mantıksal karşılaştırmalardır.

Diyelim ki okul genelinde bir devamsızlık raporu hazırlamamız gerekiyor. Raporda iki kriter var:
1. Tarih seçili ise,
2. Sınıf seçili ise,

Sınıf ve ya tarih değişkeni kullanıcı tarafından girilmezse, Bunun IF ile kontrol etmek yerine şu şekilde de karşılayabiliriz:

prmTarih ve prmSinifNo SP'ye gönderdiğimiz parametreler olsun. Seçili olmamaları halinde bunların varsayılan değerlerini "" ve -1 olarak gönderelim. Sorgumuzu şu şekilde yaparsak çözümü elde etmiş olacağız.


SELECT * FROM tbldevamsizlik td
WHERE (td.tarih = prmTarih OR prmTarih IS NULL)
AND (td.sinifNo = prmSinifNo OR prmSinifNo = -1);

***
Bu yöntemin bir de götürüsü var; performansın önemli olduğu yapılarda, ki çoğu öyledir, özellikle ana tabloda kullanılan indeksler göz önünde bulundurularak SP yazılmalıdır.

Tarih ve Sınıf numaralarının öğrenci numarası ile birlikte iki ayrı index olduğunu düşünelim:
create index tbldevamsizlik_Index1 on tbldevamsizlik (ogrenciNo, tarih);
create index tbldevamsizlik_Index2 on tbldevamsizlik (ogrenciNo, sinifNo);


Bu durumda kodu IF kontrolü ile ayırmak ve aynı kod bloğunu iki defa yazmak (kod uzasa ve tekrar etmiş olsa da) SP 'nin daha hızlı çalışmasını sağlayacaktır.
Bunun nedeni veritabanı motorunun SP için bir çalıştırma planı (execution plan) hazırlması ve bu planı SP ilk çağrıldığında kullanılan parametre/indeks eşleşmesine göre yapıp, sonraki her çağrımda aynı planı kullanması. OR yapısı kullanılırsa, indeksten faydalanma tam anlamıyla gerçekleşemeyecektir. Performans için doğru olan şu şekilde gerçekleştirimdir:


IF prmTarih IS NULL THEN
SELECT * FROM tbldevamsizlik td
WHERE (td.sinifNo = prmSinifNo);
ELSE IF prmSinifNo IS NULL THEN
SELECT * FROM tbldevamsizlik td
WHERE (td.tarih = prmTarih);
END IF;

Hiç yorum yok: