firebird de input parametre

Firebird ve Interbase veritabanları ve SQL komutlarıyla ilgli sorularınızı sorabilirsiniz. Delphi tarafındaki sorularınızı lütfen Programlama forumunda sorunuz.
Cevapla
habilkader
Üye
Mesajlar: 61
Kayıt: 14 Eki 2006 11:11

firebird de input parametre

Mesaj gönderen habilkader »

S.a

Delphide bir raporlama sayfası hazırlıyorum. Bu raporlama sayfasında 3 tane kriter var StokKodu, Depo, Tarih.
Ancak kullnıcı için stokkodu alanını boş bırakrsa tüm stoklar gelecek, yada herhengibir bir stok seçerse sadece o seçtiği stoğa ait hareketler gelecek. Aynı sey depo ve tarih için de geçerli yani kullnıcı ister 3 kriterede değer girer isterse hiçbirine girmez. isterse 1 yada 2 sine girer.

FB de bu sorgu için

Kod: Tümünü seç

Select * from Stokhareketi 
where StokKodu=:P_StokKodu and Depo=:P_Depo and Tarih=:P_Tarih
şeklinde giriş parametreli bir SP hazırladığımda kullnıcı eğer sadece Stokkodunu seçmiş depo ve Tarih seçimi yapmamış ise P_Depo ve P_Tarih parametreleri Null olarak dönmektedir ki bu da sonucu yanlış sonuç döndürmekteridr.

Bu problemi aşmak için Where ifadesinden sonraki kısmının tamamını bir giriş parametresi ile delphi tarafından alayım diye düşündüm

Delphideki formda Depo, Stok Kodu, tarih ifadelerinden hangilerini seçilmiş ise arka planda kendim bir Where ifadesi oluşturup SP ye parametre olarak göndermek istiyorum

ancak firebird tarafında

Kod: Tümünü seç

 Select * from Stokhareketleri Where :P_Sorgu
yazıyoroum ancak P_Sorgu giriş parametresini bu şekilde kullanılmasına izin vermiyor.

bu konuda nasıl bir çözüm üretebiliriz.
Kullanıcı avatarı
rsimsek
Admin
Mesajlar: 4482
Kayıt: 10 Haz 2003 01:48
Konum: İstanbul

Mesaj gönderen rsimsek »

Öncelikle perfomans için şunu söyleyebilirim, SELECT * ... ifadesindeki * yerine alanları aralarında virgülle ayırarak yazınız. İkincisi parametre zorunlu değilse yani boş bırakılabiliyorsa;

Kod: Tümünü seç

Select alan1, alan2, ... 
from Stokhareketi
where (:P_StokKodu = '' or StokKodu = :P_StokKodu)
şeklinde parametre boş veya alana eşitse şeklinde kontrol edilebilir. Bu şekilde kullanabilirsiniz.

Alan boş ise bunun yerine WHERE i hiç kullanmadan yazmak daha perfomanslıdır;

Kod: Tümünü seç

Select alan1, alan2, ... 
from Stokhareketi
Diğer parametreleri de aynı şekilde bağlayabilirsiniz. Aralarına AND koyarken her bir grubu ayrı ayrı paranteze almak gerekiyor. Burada bu tür bir kontrol yerine daha perfomanslı bir sorgu için WHERE kısmı delphi tarafta istenen bilgilere parametre değerlerine göre oluşturularak kullanılması tavsiye edilir. Yani ;

Kod: Tümünü seç

IBQuery.SQL.Clear;
IBQuery.SQL.Add('Select alan1, alan2, ... '); 
IBQuery.SQL.Add('from Stokhareketi');
if parametrelerin herhangi biri varsa then
begin
  IBQuery.SQL.Add('Where ');
  if trim(Edit1.Text) <> '' then
    IBQuery.SQL.Add('StokKodu = :P_StokKodu ');
... // aynı şekilde diğer alanlar da kontrol edilerek eklenir.
    // dikkat edilecek olan where den sonra herhangi bir parametre eklenmişse araya AND ilave edilir.
showmessage(IBQuery.SQL.Text); //varsa yazım hataları kontrol edilir!
end;
Bilgiyi paylaşarak artıralım! Hayatı kolaylaştıralım!!
habilkader
Üye
Mesajlar: 61
Kayıt: 14 Eki 2006 11:11

Mesaj gönderen habilkader »

rsimsek ilginiz için tşk ediyorum.
aslında sorun şöyle;
şimdi bi SP_SORGU adında SP yazalım

Kod: Tümünü seç

Select StokKodu, miktar, SatısFiyatı From Stokhareketi
ben delphi tarafında bu SP yi şu şekilde çağırabiliyorum

Kod: Tümünü seç

IBQuery.SQL.Text:='Select * from SP_Sorgu';
IBQuery.open;
burda sorun yok şimdi aynı SP yi birde şöyle çağırayım

Kod: Tümünü seç

IBQuery.SQL.Text:='Select * from SP_Sorgu Where StokKodu='ST001'';
IBQuery.open;
where ifadesindeki STOKKODU alanı SP içinde seçili olduğu için Stokkodu alanını delphi tarafında sorgulayabiliyorum bundada sorun yok.

şimdi SP yi biraz değiştireyim ve yeni SP aşağıdaki gibi olsun
her stoğun ayrı ayrı satış tutarlarını bulsun

Kod: Tümünü seç

Select StokKodu, Sum(Miktar*Fiyatı) as Tutar From Stokhareketi
group by StokKodu


şimdi delphi tarafında SP mi çağırıyorum

Kod: Tümünü seç

IBQuery.SQL.Text:='Select * from SP_Sorgu ';
IBQuery.open;

burda da sorun yok herşey güzel. Ancak form üzerinde bir Checkbox ve 2 adette Maskedit var. Yani kullnıcı isterse Checboxı işaretleyerek maskeditlere 2 tarih girip bu 2 tarih arasındaki hareketlerin tutarlarını görmek isteyebilir. bu durumda delphi tarafından SP yi şöyle çağıyorum

Kod: Tümünü seç

IBQuery.SQL.Text:='Select * from SP_Sorgu where Tarih between :Tar1 and :tar2';
IBQuery.open;


çağıramıyorum çünkü SP içinde Tarih alanı seçilmemiş
SP içinde Tarih alanını seçersem bu kez tarihe görede Group by kısmına Tarih alanında göre gruplama yapmam gerekecek ki bu sefer yanlış sonuç dönecek

Sonuç:
SP de Select ile seçilmemiş bir alan Delphi tarafından Where ile karşılaştırlamıyor.
SP tarafında eğer o alanı seçersem ki SUM kullnıyorsam o alanı gruplamam da gerekecek, gruplarsam yanlış bir sonuç kümesi dönüyor geriye tek bir çözüm kalıyor SP yi çöpe atıp delphi tarafından SQL kodlarla yapmak.
bu durumda da SP kullanmayarak performansı düşürmüş olacağız
bir türlü işin içinden çıkamadım lütfen yardım.
Kullanıcı avatarı
rsimsek
Admin
Mesajlar: 4482
Kayıt: 10 Haz 2003 01:48
Konum: İstanbul

Mesaj gönderen rsimsek »

İyice ayrıntılı yazmışsın ben sonuca göre cevaplıyayım. Eğer return olarak TARIH diye bir alan dönüyorsa ;

Kod: Tümünü seç

IBQuery.SQL.Text:='Select * from SP_Sorgu where Tarih between :Tar1 and :tar2';
IBQuery.ParamByName('Tar1').AsDateTime := DateTimePicker1.Date;
IBQuery.ParamByName('Tar2').AsDateTime := DateTimePicker2.Date;
IBQuery.open;
şeklinde çalışması gerekir. Ayrıca WHERE içindeki alanın GROUP BY da belirlenmesine gerek yok yanlış biliyorsunuz :idea: SELECT içinde kullanılacaksa gerek var.
Sonuçta Stored Procedur (SP) yi bir TABLE gibi kullanabilirsiniz.
Bilgiyi paylaşarak artıralım! Hayatı kolaylaştıralım!!
Cevapla