PDA

View Full Version : سوال: جستجوی چندگانه بدون خروجی !



hamedjim
چهارشنبه 07 مرداد 1394, 20:08 عصر
سلام به همگی.
دوستان من در برنامه‌م فرمی برای جستجو به این شکل قرار دادم:

133702

فیلدهای تاریخ بارگیری و تاریخ تخلیه به صورت رشته‌ای و بقیه فیلدها به صورت عددی تعریف شدند.
برای جستجو کد زیر رو نوشتم اما خروجی نداره. لطفا اگه جایی رو اشتباه کردم متذکر بشید. ممنونم



procedure TFormSearch.BitBtnSearchClick(Sender: TObject);
var
Filter: String;
begin
Filter:='';

if MaskEditLoadingFrom.Text<>' / / ' then
Filter:=Filter + ' AND (LoadingDate>= '+ QuotedStr(MaskEditLoadingFrom.Text) + ')';

if MaskEditLoadingTo.Text<>' / / ' then
Filter:=Filter + ' AND (LoadingDate<= '+ QuotedStr(MaskEditLoadingTo.Text) + ')';

if MaskEditOffLoadingFrom.Text<>' / / ' then
Filter:=Filter + ' AND (OffLoadingDate>= '+ QuotedStr(MaskEditOffLoadingFrom.Text) + ')';

if MaskEditOffLoadingTo.Text<>' / / ' then
Filter:=Filter + ' AND (OffLoadingDate<= '+ QuotedStr(MaskEditOffLoadingTo.Text) + ')';

if EditWayBillNo.Text<>'' then
Filter:=Filter + ' AND (WayBillNo= '+ EditWayBillNo.Text + ')';

if EditLoadingCost.Text<>'' then
Filter:=Filter + ' AND (LoadingCost= '+ EditLoadingCost.Text + ')';

if EditLoadWeight.Text<>'' then
Filter:=Filter + ' AND (LoadWieght= '+ EditLoadWeight.Text + ')';

if EditOffLoadWeight.Text<>'' then
Filter:=Filter + ' AND (OffLoadWieght= '+ EditOffLoadWeight.Text + ')';



with ADOQuerySearch do
begin
if Filter='' then
begin
Close;
SQL.Clear;
SQL.Text:= 'SELECT * FROM List';
Open;
end
else
begin
Close;
SQL.Clear;
SQL.Text:= 'SELECT * FROM List WHERE 1=1' + Filter;
Open;
end;
end;

pbm_soy
پنج شنبه 08 مرداد 1394, 03:13 صبح
من کد شما را دقیق نخوندم ولی پینهادی که میتونم بدم اینه که دستور sql را تیکه تیکه بزرگ کن یعنی اول ببین بدون شرط کار میکنه و جوابی ازش میگیری> یعنی بدون شرط باید کل رکوردهای جدول را باید برگرداند و سپس یک شرط اضافه کن و نتیجه را بررسی کن و همینطور ادامه بده!
معمولا در چنین کدهایی بهترین کار همین است تا ایراد کار پیدا شود

hamedjim
پنج شنبه 08 مرداد 1394, 08:02 صبح
اول ببین بدون شرط کار میکنه و جوابی ازش میگیری

ممنون از راهنمایی. اما با این کدی که من نوشتم، اگر هیچ مقداری وارد نکنم، برنامه بدون شرط اجرا و تمام رکوردها نمایش داده میشه.
هر بار که مقداری در MaskEditها یا Editها نوشته بشه، شرط بزرگتر میشه.
به عنوان مثال وقتی من هیچ مقداری به عنوان شرط جستجو وارد نمی کنم، نتیجه میشه:


SQL.Text:= 'SELECT * FROM List WHERE 1=1'


و اگر "تاریخ تخلیه/ از" رو با 94/05/08 مقداردهی کنم:


SQL.Text:= 'SELECT * FROM List WHERE 1=1 AND OffLoadingDate>=:94/05/08'


اما جالب اینجاست که در حالت دوم هم تمام رکوردها نمایش داده شدند!!!!

hp1361
پنج شنبه 08 مرداد 1394, 13:57 عصر
سلام

پیشنهاد میکنم از این نحوه کدنویسی استفاده کنید تا هم خوانایی کارتون بالاتر باشه و هم مشکل یابیش و هم امنیتش!


procedure TForm1.Button1Click(Sender: TObject);
begin
with FDQuery1 do
begin
Close;
SQL.Clear;
SQL.Add('SELECT * FROM Table_Name WHERE LoadingDate>= :ParamLoadingDateFrom AND LoadingDate<= :ParamLoadingDateTo');
Params.ParamByName('ParamLoadingDateFrom').Value:= MaskEditLoadingFrom.Text;
Params.ParamByName('ParamLoadingDateTo').Value:=Ma skEditLoadingTo.Text;
Open();
if IsEmpty then
ShowMessage('نتیجه ای یافت نشد!');
end;
end;


مقادیر متغیرها رو بصورت پارامتر به SQL ارسال کرده ایم (پارامتر ها با علامت : قبل از نامشون مشخص می شوند.)

باقی پارامتر ها رو هم به همین صورت به راحتی می تونید به کد SQL و لیست پارامتر های مربوطه اضافه کنید

موفق باشیم

hamedjim
پنج شنبه 08 مرداد 1394, 15:04 عصر
سلام

پیشنهاد میکنم از این نحوه کدنویسی استفاده کنید تا هم خوانایی کارتون بالاتر باشه و هم مشکل یابیش و هم امنیتش!

سلام.
تا قبل از این، من به همین روش برای جستجو و فیلترسازی عمل می‌کردم. اما چون این بار تعداد آیتم‌های جستجو زیاده و در هر لحظه کاربر ممکنه از یک یا چندتای اونها استفاده نکنه، به نظرم رسید به این شکل عمل کنم.
چون با اضافه کردن پارامتر برای همه آیتم‌ها با یه مشکل روبرو هستم: زمانی که کاربر یک آیتم رو خالی میذاره (به عنوان مثال MaskEditLoadingDate)، همیشه با پیغام "نتیجه‌ای یافت نشد" روبرو میشیم.
ممنون میشم راهنمایی کنید.

hamedjim
پنج شنبه 08 مرداد 1394, 15:25 عصر
من موقتا با این روش مشکل سرچ رو حل کردم ( که البته معتقدم روش اصولی و درستی نباید باشه):



with ADOQuerySearch do
begin
Close;
SQL.Clear;
SQL.Add('SELECT * FROM List WHERE 1=1');
if MaskEditLoadingFrom.Text<>' / / ' then
SQL.Add(' AND LoadingDate>= :PLoadingDateFrom');
if MaskEditLoadingTo.Text<>' / / ' then
SQL.Add(' AND LoadingDate<= :PLoadingDateTo');
if MaskEditOffLoadingFrom.Text<>' / / ' then
SQL.Add(' AND LoadingDate>= :POffLoadingDateFrom');
if MaskEditOffLoadingTo.Text<>' / / ' then
SQL.Add(' AND LoadingDate<= :POffLoadingDateTo');
if EditLoadWeight.Text<>'' then
SQL.Add(' AND LoadWieght>= :PLoadWieght');
if EditOffLoadWeight.Text<>'' then
SQL.Add(' AND OffLoadWeight<= :POffLoadWeight');
if EditLoadingCost.Text<>'' then
SQL.Add(' AND LoadingCost>= :PLoadingCost');
if EditWayBillNo.Text<>'' then
SQL.Add(' AND WayBillNo<= :PWayBillNo');

if MaskEditLoadingFrom.Text<>' / / ' then
Parameters.ParamByName('PLoadingDateFrom').Value:= MaskEditLoadingFrom.Text;
if MaskEditLoadingTo.Text<>' / / ' then
Parameters.ParamByName('PLoadingDateTo').Value:= MaskEditLoadingTo.Text;
if MaskEditOffLoadingFrom.Text<>' / / ' then
Parameters.ParamByName('POffLoadingFrom').Value:= MaskEditOffLoadingFrom.Text;
if MaskEditOffLoadingTo.Text<>' / / ' then
Parameters.ParamByName('POffLoadingTo').Value:= MaskEditOffLoadingTo.Text;
if EditLoadWeight.Text<>'' then
Parameters.ParamByName('PLoadWeight').Value:= EditLoadWeight.Text;
if EditOffLoadWeight.Text<>'' then
Parameters.ParamByName('POffLoadWeight').Value:= EditOffLoadWeight.Text;
if EditLoadingCost.Text<>'' then
Parameters.ParamByName('PLoadingCost').Value:= EditLoadingCost.Text;
if EditWayBillNo.Text<>'' then
Parameters.ParamByName('PWayBillNo').Value:= EditWayBillNo.Text;

Open;
if IsEmpty then
ShowMessage('نتیجه ای یافت نشد!');
end;

hp1361
پنج شنبه 08 مرداد 1394, 15:57 عصر
سلام مجدد

چرا درست نباشه؟! اتفاقاً به نظر من ایده خوبی رو اجرا کردی.یه چیزی هم به ما یاد دادی!

البته میتونی در همون قسمت بالا که با شرط چک میکنی و پارامتر رو تعریف میکنی همونجا مقدارش رو هم درون شرط تخصیص بدی(دو بار شرط چک نشه)

ضمن اینکه نیازی به Where 1=1 هم نیست

موفق باشیم

hamedjim
پنج شنبه 08 مرداد 1394, 16:13 عصر
به نظر من ایده خوبی رو اجرا کردی... همونجا مقدارش رو هم درون شرط تخصیص بدی(دو بار شرط چک نشه)
البته با این تذکر بجا به نظرم حالا یه‌کم منطقی‌تر شد.



ضمن اینکه نیازی به Where 1=1 هم نیست

من فکر می کنم این کار لازمه. با این کار عبارت WHERE رو به دستور SQL اضافه کردم و حالا دیگه هیچ وقت با خطا مواجه نمیشم ( با توجه به اینکه تمام دستوراتی که Add میشن با عبارت AND شروع شدند.)
اگر این کار رو نمی کردم و کاربر هیچ یک از آیتم های جستجو رو پر نمی‌کرد با خطا مواجه میشدم.

hp1361
پنج شنبه 08 مرداد 1394, 16:17 عصر
خوب اینطوری شما همیشه یه اتصال به بانک و قطع ارتباط رو خواهید داشت! بهتر اینه که قبل از هر چیزی چک بشه که کاربر حداقل یکی از فیلدها رو پر کرده باشه! حالا هم میتونی پیغامی در این خصوص به کاربر نشون بدی و هم میتونی چیزی نشون ندی!

hamedjim
پنج شنبه 08 مرداد 1394, 16:30 عصر
خوب اینطوری شما همیشه یه اتصال به بانک و قطع ارتباط رو خواهید داشت!
این حرف کاملا قبول و منطقی.
اما با توجه به اینکه محتوای تمام SQL.Add با AND شروع میشه، من نیاز دارم تا یه شرط بی تاثیر قبل از اون قرار بدم.
به عنوان مثال :


with ADOQuerySearch do
begin
Close;
SQL.Clear;
SQL.Add('SELECT * FROM List WHERE ');

...

اگر هر فیلدی مقداردهی بشه نتیجه به این شکل درمیاد:


SELECT * FROM List WHERE AND ...

یوسف زالی
جمعه 09 مرداد 1394, 00:50 صبح
چرا از اس پی استفاده نکردید؟ دیتابیستون اس کیو اله؟

hamedjim
جمعه 09 مرداد 1394, 23:33 عصر
چرا از اس پی استفاده نکردید؟ دیتابیستون اس کیو اله؟
تسلط چندانی به مبحث StorP ندارم. اما به نظر می‌رسه باید به سرعت واردش بشم.
البته برای این برنامه خاص دیتابیس اکسس مورد نیاز بود.

hp1361
شنبه 10 مرداد 1394, 11:44 صبح
چرا از اس پی استفاده نکردید؟ دیتابیستون اس کیو اله؟

سلام

با توجه به اینکه تعداد پارامتر های SQL ایشان متغیره، آیا امکانش هست یک SP با تعداد پارامتر متغیر نوشت؟ یا نه باید برای هر تعداد پارامتر SP جداگانه نوشت؟

یوسف زالی
شنبه 10 مرداد 1394, 13:39 عصر
سلام.
تعداد پارامتر متغیر نیست. فقط استفاده شدنشونه که متغیره.
تمام آیتم ها رو بصورت پارامتر می فرستند، و در سلکت مربوطه کد رو به این صورت می نویسند:


where @Param1 in (0, AField) and @Param2 in (0, AField2) and ..

یا به هر نحو مشابه دیگه.

hp1361
شنبه 10 مرداد 1394, 14:07 عصر
سلام.
تعداد پارامتر متغیر نیست. فقط استفاده شدنشونه که متغیره.
تمام آیتم ها رو بصورت پارامتر می فرستند، و در سلکت مربوطه کد رو به این صورت می نویسند:


where @Param1 in (0, AField) and @Param2 in (0, AField2) and ..

یا به هر نحو مشابه دیگه.

یعنی اگر @Param1 مقدارش از طرف برنامه خالی ارسال بشه در دستور Select درنظر گرفته نخواهد شد؟

اگر ممکنه کارکرد (0, AField) رو توضیح بدید.

ممنون

یوسف زالی
شنبه 10 مرداد 1394, 14:30 عصر
اگر پارامتر خالی (در اینجا به دلیل عددی بودن، صفر) رد بشه در سلکت تاثیری نداره.
بهتره همیشه تمام پارامترها مقداردهی شده باشند.
برای نال هم می شه به همین منوال نوشت.
اون تیکه in (AField, 0) -- sql code هم می گه پارامتر یا صفر باشد یا این که با مقدار AField برابر باشد.