I have tried to filter through an ado database table on delphi.
I have a dbgrid connected to the query(qryData), as soon as this code executes then the dbgrid goes blank and nothing further happens. Even if I type in a valid field name, it should then display it in the dbgrid but it shows nothing. What am I doing wrong?
procedure TfrmProjects.cbxColumnsSelect(Sender: TObject);
begin
if edtsearch.Text = '' then
begin
showmessage('The search field should be entered');
exit;
end
else
begin
ssearch:= edtsearch.Text;
showmessage(ssearch);
end;
if cbxColumns.ItemIndex = -1 then
begin
showmessage('Please select a field');
exit;
end
else
begin
scolumn:= cbxColumns.Items[cbxColumns.itemindex];
showmessage(scolumn);
end;
with dmUsers do
begin
with qryData do
begin
sql.Clear;
sql.Text := 'Select * FROM tbl_projects where' + quotedstr(scolumn) + ' = ' +quotedstr(ssearch);
open;
end;
end;
The following works for me. You will need to change the references to qryData to dmUsers.qryData. Btw, try and avoid using "with ..."
Note that the SQL you are constructing isn't ideal, because it doesn't take account of whether the column being searched upon is of a datatype which requires the value specified in the query to be surrounded in quotes. The column name doesn't need to be in quotes, but may need square brackets [ ] around it if it has embedded spaces. The fact that you included quotes around the column name was the reason the grid went blank - what you were asking the Sql search engine on the server for is all rows where 'one string' = 'another string', which is false for any row so none is returned. Btw, this is related to Sql examples you sometimes see which have a where clause like 'where 1 = 2'; that's never true, of course, and the idea is to force the search engine to parse the query without returning any rows.
As @mostkito-x commented, one of the main problems with the original version of your query was lack of space between the elements of the query Use spaces liberally so you can see what you're doing. When you're having trouble with a query no bad thing to put its text into a memo (set to a fixed-pitched font like Courier) on your form, so you can eyeball whether you're actually constructing the query you think you are.
Btw, in case you hadn't gathered, using QuotedStr around the search value for string datatypes has the advantage of correctly handling the case where the search value has an embedded quote (like o'Reilly).
procedure TForm1.CbxColumnNameClick(Sender: TObject);
// NOTE: The following code assumes that either qryData is open when it is called
// or has persistent TFields defined
var
FieldName,
ValueToSearch,
Sql : String;
UseQuotedValue : Boolean;
begin
FieldName := cbxColumnName.Text;
if FieldName = '' then begin
ShowMessage('No field selected for search.');
Exit;
end;
UseQuotedValue := qryData.FieldByName(FieldName).DataType in [ftString, ftWideString, ftMemo];
ValueToSearch := edtSearch.Text;
if UseQuotedValue then
ValueToSearch := QuotedStr(ValueToSearch);
Sql := 'select * from tblProjects where ' + FieldName + ' = ' + ValueToSearch;
if qryData.Active then
qryData.Close;
qryData.SQL.Text := Sql;
qryData.Open;
end;
Also with queries of this type read up on "SQL Injection" malware risks (http://en.wikipedia.org/wiki/Sql_injection). The received wisdom is that a measure to reduce the risk of this is to use parameterized queries. Unfortunately for your task, although you can specify the column value to be matched as a parameter, you can't parameterize the column name in ADO.
To use a parameterized query, the Sql would look something like
Select * from tblProjects where SomeColumn = :somevalue
Then, in the IDE Object Inspector you'd need to define a parameter on qryData and, before executing the query, do qryData.Parameters.ParamByName('somevalue').Value := edtSearch.Text. But, like I said, you can't parameterize the column name to search on.