PDA

View Full Version : سوال: No value given for one or more required parameters



_abiriamir
یک شنبه 03 خرداد 1388, 15:52 عصر
با سلام به همگی
من قطعه کد زیر را مینویسم اما با
"error:"No value given for one or more required parameters
مواجه میشوم.
چکار کنم؟



procedure TMainfrm.Find_editChange(Sender: TObject);
begin
if find_edit.Text<>'' then
begin
ADOQuery1.Active:=false;
ADOQuery1.SQL.Clear;

case column.ItemIndex of
0:begin
ADOQuery1.SQL.Add('select * from table1 where ردیف=:find');
ADOQuery1.Parameters.ParamByName('find').Value:=st rtoint(find_edit.Text);
end;

1:begin
ADOQuery1.SQL.Add('select * from table1 where نام like :find');
ADOQuery1.Parameters.ParamByName('find').Value:=fi nd_edit.Text;
end;

2:begin
ADOQuery1.SQL.Add('select * from table1 where بدهکاری =:find');
ADOQuery1.Parameters.ParamByName('find').Value:=st rtocurr(find_edit.Text);
end;

3:begin
ADOQuery1.SQL.Add('select * from table1 where بستانکاری=:find');
ADOQuery1.Parameters.ParamByName('find').Value:=st rtocurr(find_edit.Text);
end;

4:begin
ADOQuery1.SQL.Add('select * from table1 where شماره تلفن =:find');
ADOQuery1.Parameters.ParamByName('find').Value:=fi nd_edit.Text;
end;

5:begin
ADOQuery1.SQL.Add('select * from table1 where شماره موبایل =:find');
ADOQuery1.Parameters.ParamByName('find').Value:=fi nd_edit.Text;
end;

6:begin
ADOQuery1.SQL.Add('select * from table1 where ایمیل like :find');
ADOQuery1.Parameters.ParamByName('find').Value:=fi nd_edit.Text;
end;

7:begin
ADOQuery1.SQL.Add('select * from table1 where توضیحات like :find');
ADOQuery1.Parameters.ParamByName('find').Value:=fi nd_edit.Text;
end;

end; //End of case


ADOQuery1.open;
DBGrid1.DataSource.DataSet:=ADOQuery1;
ADOQuery1.Active:=true;

end // end if
else
begin
ADOQuery1.Active:=false;
ADOQuery1.SQL.Clear;
ADOQuery1.SQL.Add('select * from table1');
ADOQuery1.open;
DBGrid1.DataSource.DataSet:=ADOQuery1;
ADOQuery1.Active:=true;

end;
end;




راستی column یک combobox میباشد.
البته این تمام ماجرا نیست بلکه این برنامه فقط در مورد جستجوی نام عمل میکند و در بقیه موارد error میدهد.

لطفا کمک کنید.

Saeed_m_Farid
یک شنبه 03 خرداد 1388, 19:38 عصر
سلام
اول 2 تا نکته :


عنوان تاپیک رو یه چیز با معنی بذارید تا هم بعدا بشه بهش مراجعه کرد و هم به درد سایر دوستان هم بخوره.
کدها رو تو تگ کد بذارید که بشه خوندشون، یه نگاه به پستتون بندازید ببینین خودتون متوجه میشین چی نوشتین؟

حالا در مورد سوال :


column یه اسم کلیدی هست و ممکنه بعدا به مشکل بخورید. بعدش هم مگه ComboBox شما Text نداره که از ItemIndex اش استفاده کردین که اینهمه هم case بنویسید، میمونه نوع فیلد که اونهم شما Variant گذاشتین و میتونین هرچیزی انتساب بدین و لازم نیست تبدیل نوع کنین.
چرا فیلد هاتون فارسی هستن؟ اینهمه هم کاراکتر 'ی' تو نام فیلدها دارین، فیلد فارسی همینطوریش واستون مشکل ایجاد میکنه، چه برسه کاراکترای 'ی' یا 'ک' و... داشته باشین. مطمئن باشین موقع تحویل (اگه بخواین سیستمی که نوشتین تحویل بدین) مشکلات unicode و فارسی و ... خواهید داشت.
من منطق شما رو از این کد نمیفهمم؛ خوب شما که SQL نوشتین مستقیم همونجا مقداردهی میکردین، این بازی با پارامترها چیه؟
پیشنهاد من اینه : اولا حتماً نام فیلد ها رو انگلیسی کنید و نام ComboBox رو عوض کنید؛ ثانیا لیست ComboBox رو از نام فیلدها پر کنید (با استفاده از یه حلقه و Fields)، و از روی لیست کوئری رو درست کنید، یعنی بعد از پر کردن لیست ComboBox کد OnChange برای Edit میشه اینطوری :
procedure TMainForm.find_editChange(Sender: TObject);
var
tmpStr: String;

begin
if find_edit.Text<>'' then begin

ADOQuery1.Active := false;

case ADOQuery1.Fields.FindField(column.Text).DataType of
ftString,
ftVarBytes,
ftMemo,
ftFmtMemo : tmpStr := ' Like %';
else
tmpStr := ' = ';
end;

ADOQuery1.SQL.Text := 'Select * From Table1 Where ' +
column.Text + tmpStr + find_edit.Text;

ADOQuery1.open;
DBGrid1.DataSource.DataSet:=ADOQuery1;
ADOQuery1.Active:=true;

end else begin

ADOQuery1.Active:=false;
ADOQuery1.SQL.Clear;
ADOQuery1.SQL.Add('select * from table1');
ADOQuery1.open;
DBGrid1.DataSource.DataSet:=ADOQuery1;
ADOQuery1.Active:=true;

end;
end;


موفق باشید.

shervin farzin
دوشنبه 04 خرداد 1388, 00:59 صبح
سلام

مگه ComboBox شما Text نداره که از ItemIndex اش استفاده کردین که اینهمه هم case بنویسید
فرمايش شما كاملا درسته اگر نام فيلهاي Database و Item هاي Combobox مثل هم باشند اما
اگر ايشون نام فيلهاي Database رو از حالت فارسي خارج كنند ( كه توصيه ميكنم حتما اين كار رو
انجام بدند ) ، اون وقت خوندن Text از Combobox كاري از پيش نمي بره و در اين مورد من با
ايشون در استفاده از ItemIndex موافقم .
با توجه به نوع فيلدهاي جدول شما امكان داره كه كد زير با مقدار كمي تغييرات نتيجه داشته باشه .

var
sql_text:string;
begin
sql_text:='select * from table1';
if find_edit.Text<>'' then
begin
case column.ItemIndex of
0:sql_text:=sql_text+' where Row = :find';
1:sql_text:=sql_text+' where Name = :find';
2:sql_text:=sql_text+' where Debtor = :find';
3:sql_text:=sql_text+' where Creditor = :find';
4:sql_text:=sql_text+' where Phone = :find';
5:sql_text:=sql_text+' where Mobile = :find';
6:sql_text:=sql_text+' where Email = :find';
7:sql_text:=sql_text+' where Comment = :find';
end;
ADOQuery1.Parameters.ParamByName('find').Value:=fi nd_edit.Text;
end;
// Executing SQL Statement
ADOQuery1.SQL.Text:=sql_text;
DBGrid1.DataSource.DataSet:=ADOQuery1;
ADOQuery1.Active:=true;

در ضمن به نظرم نمياد كه خط قرمز رنگ در كد منطقي باشه . به هر ترتيب چون خودتون استفاده
كرده بوديد من هم تغييرش ندادم ، ولي اگر برنامه با Error مواجه شد مراقب اين خط باشيد .
موفق باشيد .

Saeed_m_Farid
دوشنبه 04 خرداد 1388, 10:41 صبح
اگر نام فيلهاي Database و Item هاي Combobox مثل هم باشند اما
اگر ايشون نام فيلهاي Database رو از حالت فارسي خارج كنند ( كه توصيه ميكنم حتما اين كار رو
انجام بدند ) ، اون وقت خوندن Text از Combobox كاري از پيش نمي بره و در اين مورد من با
ايشون در استفاده از ItemIndex موافقم .من تو پست قبل عرض کردم که لازم نیست تو Design mode لیست ComboBox پر بشه :
پست قبلی من : ثانیا لیست ComboBox رو از نام فیلدها پر کنید (با استفاده از یه حلقه و Fields)مثلا میشه تو FormCreate لیست رو اینجوری پر کرد، و لازم نیست دیگه نگران عوض شدن نام فیلدها باشیم، (البته من فرض می کنم ایشون نام کامبوباکس رو هم درست کردن) یعنی اینجوری :
procedure TMainForm.FormCreate(Sender: TObject);
var
idx: Integer;
begin
with ADOQuery1 do begin
Active := False;
SQL.Text := 'Select * From Table1';
Open;
cbFields.Items.Clear;
for idx := 0 to Fields.Count - 1 do
cbFields.Items.Add(Fields[idx].FieldName);
cbFields.ItemIndex := 0;
end;
end;

با توجه به نوع فيلدهاي جدول شما امكان داره كه كد زير با مقدار كمي تغييرات نتيجه داشته باشه .فکر کنم بکمی بیشتر از مقدار کمی!، نتیجه بده، چون شما همه فیلدها رو به یه چشم دیدین، یعنی تو کد ایشون به فرض ممکنه قرار باشه کوئری مربوط به فیلدهای رشته، ممو، varchar و ... از Like استفاده کنن و واسه فیلدهای دیگه از مساوی؛ واسه همین کد زیر رو گذاشته بودم :

case ADOQuery1.Fields.FindField(cbFields.Text).DataType of
ftString,
ftVarBytes,
ftMemo,
ftFmtMemo : tmpStr := ' Like %';
else
tmpStr := ' = ';
end;
در ضمن نوع کدها میتونه یکی از موارد زیر باشه که نسبت به اونا هم میشه تصمیم گیری کرد :
ftUnknown, ftString, ftSmallint, ftInteger, ftWord,
ftBoolean, ftFloat, ftCurrency, ftBCD, ftDate, ftTime, ftDateTime,
ftBytes, ftVarBytes, ftAutoInc, ftBlob, ftMemo, ftGraphic, ftFmtMemo,
ftParadoxOle, ftDBaseOle, ftTypedBinary, ftCursor, ftFixedChar, ftWideString,
ftLargeint, ftADT, ftArray, ftReference, ftDataSet, ftOraBlob, ftOraClob,
ftVariant, ftInterface, ftIDispatch, ftGuid, ftTimeStamp, ftFMTBcd
مثلا واسه یه فیلد از نوع ftBlob یا ftGraphic و ... نمیشه از موارد بالا استفاده کرد، اونا هم راه خودشون رو دارن ...

با تشکر.

shervin farzin
دوشنبه 04 خرداد 1388, 11:08 صبح
سلام

فکر کنم بکمی بیشتر از مقدار کمی!، نتیجه بده چون شما همه فیلدها رو به یه چشم دیدین
خير ، منظورم از تغيير تنظيم ورودي هاي سليقه اي بود مثل اضافه كردن كاما يا خط تيره ، در غير اين صورت
اين كد صد در صد جواب ميده . در مورد انواع داده هم بايد عرض كنم من به همه به يك چشم نگاه نكردم و
عمدا به همين منظور از پارامتر در كدم استفاده كردم چون فرايند Type Cast رو براي انواع مورد استفاده ايشون
انجام ميده و نيازي به درگيري با انواع داده به طور مستقيم نيست .
به هر ترتيب اگر دوستمون مايل باشه انواع داده بيشتري رو به صورت جدا مديريت كنه فرمايش شما كاملا متينه .
موفق باشيد .

Saeed_m_Farid
دوشنبه 04 خرداد 1388, 14:11 عصر
سلام

خير ، منظورم از تغيير تنظيم ورودي هاي سليقه اي بود مثل اضافه كردن كاما يا خط تيره ، در غير اين صورت
اين كد صد در صد جواب ميده . در مورد انواع داده هم بايد عرض كنم من به همه به يك چشم نگاه نكردم و
عمدا به همين منظور از پارامتر در كدم استفاده كردم چون فرايند Type Cast رو براي انواع مورد استفاده ايشون
انجام ميده و نيازي به درگيري با انواع داده به طور مستقيم نيست .
به هر ترتيب اگر دوستمون مايل باشه انواع داده بيشتري رو به صورت جدا مديريت كنه فرمايش شما كاملا متينه .
موفق باشيد .

علیک سلام

من فقط منظورم اینه : اگه رشته بود از LIKE و در غیر اینصورت از = استفاده بشه. حالا نحوه انجام این کار رو هم تو پست هام آوردم. کاری با TypeCast و مدیریت نوع داده و اینا نداشتم.
این موضوع رو هم بخاطر این مطرح کردم که دوستمون تو پست اولش واسه ItemIndex های مختلف Like یا = استفاده کرده بودن.

با تشکر.

_abiriamir
دوشنبه 04 خرداد 1388, 22:20 عصر
طبق فرماشات دوستان گرامی کد قبل را به کد زیر تغییر دادم اما هنوز مشکل هایی دارد از جمله فقط داده های عددی را پیدا میکند.
البته نام ها را نیز تغییر دادم



procedure TMainfrm.Find_editChange(Sender: TObject);

if clmn.Text=('Row')then tmpstr:=' = '
else if clmn.text=('Deptor')then tmpstr:=' = '
else if clmn.text=('creditor')then tmpstr:=' = '
else (*'Name', 'Phone', 'Mobile', 'Email', 'Comment':*) tmpstr:= ' like :';

ADOQuery1.SQL.Text := ('Select * From Table1 Where ' +
clmn.Text + tmpStr + find_edit.Text);

ADOQuery1.open;
DBGrid1.DataSource.DataSet:=ADOQuery1;
ADOQuery1.Active:=true;

end else begin

ADOQuery1.Active:=false;
ADOQuery1.SQL.Clear;
ADOQuery1.SQL.Add('select * from table1');
ADOQuery1.open;
DBGrid1.DataSource.DataSet:=ADOQuery1;
ADOQuery1.Active:=true;

end;

end;



clmn اسم combobox من میباشد و item خای آن به ترتیب

Row
Name
Debtor
Creditor
Phone
Mobile
Email
Comment

میباشد.

با تشکر از همگی

shervin farzin
سه شنبه 05 خرداد 1388, 02:42 صبح
سلام
اجازه بديد من اول در مورد دستور Like يه توضيح مختصر بدم .
اگر شما بخوايد تمام فيلدهايي رو از جدولتون برگردونيد كه كلمه 'bcd' در فيلد Name وجود داشته
باشه ، بايد بنويسيد :

select * from table1 where name Like '%bcd%'
در كد فوق علامت % مثل علامت * در DOS عمل ميكنه ، يعني به جاي اين كاركتر هر مقداري
ميتونه قرار بگيره . اگر جسجتوي فوق رو بخوايد براي تمام مقاديري انجام بديد كه با عبارت 'bcd'
شروع ميشن بايد بنويسيد :

select * from table1 where name Like 'bcd%'
يعني اولش با bcd شروع بشه و در ادامه هر مقداري بتونه قرار بگيره .
اگر فرض كنيد شما بخوايد تمام مقاديري كه فقط مقدار 'bcd' هستند رو برگردونيد علاوه بر اين كه
مي تونيد از علامت = استفاده كنيد ، مي تونيد Like رو هم بنويسيد ولي بدون كاركترهاي % در
ابتدا و انتهاي رشته ، به عبارت ديگه دو كد زير به يك شكل عمل ميكنن :

select * from table1 where name = 'bcd'

select * from table1 where name like 'bcd'
حالا برگرديم به سوال شما ، اگه شما مايل باشيد با انتخاب كردن گزينه Name از Combobox و
نوشتن يك عبارت در Find_Edit ، جستجو عينا براي مقاديري انجام بشه كه مساوي با رشته
ورودي كاربر هستن هيچ نيازي به استفاده از دستور Like نداريد و با علامت = كارتون انجام ميشه
اما اگر منظور شما پيدا كردن تمام مقادري هست كه شامل رشته ورودي كاربر در Find_Edit ميشه
بايد از دستور Like و كاركتر هاي % استفاده كنيد . علامت : Like كه در كدتون نوشتيد اشتباهه .
بنابر اين كد برنامه شما رو ميشه به شكل زير تغيير داد :

var
sql_text:string;
begin
sql_text:='select * from table1';
if Find_Edit.Text <> '' then
begin
case clmn.ItemIndex of
0,2,3:sql_text:=sql_text+' where '+clmn.Items.Strings[clmn.ItemIndex]+' = '+Find_Edit.Text;
else sql_text:=sql_text+' where '+clmn.Items.Strings[clmn.ItemIndex]+' like '+QuotedStr('%'+Find_Edit.Text+'%');
end;
end;
ADOQuery1.SQL.Text:=sql_text;
DBGrid1.DataSource.DataSet:=ADOQuery1;
ADOQuery1.Active:=true;

يه نكته ديگه ، هنگامي كه مينويسيد ADOQuery1.open در واقع مقدار Active رو True كرديد . پس نيازي به نوشتن ADOQuery1.Active := true نداريد .
موفق باشيد .