我试图在delphi上过滤ado数据库表。
我有一个dbgrid连接到查询(qryData),一旦执行此代码,dbgrid就会变为空白,并且不会发生任何其他事情。即使我输入有效的字段名称,它也应该在dbgrid中显示它,但它什么也没显示。我做错了什么?
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;
答案 0 :(得分:1)
以下适用于我。您需要将对qryData的引用更改为dmUsers.qryData。顺便说一句,尽量避免使用"与..."
请注意,您正在构建的SQL并不理想,因为它没有考虑被搜索的列是否是一种数据类型,该数据类型要求查询中指定的值被引号括起来。列名称不需要在引号中,但如果它具有嵌入空格,则可能需要方括号[]。你在列名称中包含引号的事实是网格空白的原因 - 你在服务器上询问Sql搜索引擎的是所有行,其中包含一个字符串' ='另一个字符串',对于任何行都是false,因此不返回任何字符串。顺便说一句,这与你有时会看到哪些有一个where子句的Sql例子有关,例如'其中1 = 2&#39 ;;当然,这是不正确的,并且想法是强制搜索引擎解析查询而不返回任何行。
正如@ mostkito-x所评论的那样,查询原始版本的主要问题之一是查询元素之间缺少空间大量使用空格以便您可以看到自己正在做的事情。如果您在查询中遇到问题并没有什么坏处,可以将其文本放入表单上的备忘录(设置为Courier等固定字体),这样您就可以了解自己是否真正构建了查询你以为你是。
顺便说一句,如果您没有收集,使用QuotedStr围绕字符串数据类型的搜索值,可以正确处理搜索值具有嵌入引用的情况(如o&#39; Reilly)。< / p>
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;
此类查询也可以读取&#34; SQL注入&#34;恶意软件风险(http://en.wikipedia.org/wiki/Sql_injection)。收到的智慧是,降低风险的措施是使用参数化查询。不幸的是,虽然您可以指定要匹配的列值作为参数,但您无法在ADO中参数化列名称。
要使用参数化查询,Sql看起来像
从tblProjects中选择*,其中SomeColumn =:somevalue
然后,在IDE Object Inspector中,您需要在qryData上定义一个参数,并在执行查询之前执行qryData.Parameters.ParamByName(&#39; somevalue&#39;)。值:= edtSearch 。文本。但是,就像我说的那样,你不能参数化列名来搜索。
答案 1 :(得分:0)
从我所看到的问题出在这一行:
sql.Text := 'Select * FROM tbl_projects where' + quotedstr(scolumn) + ' = ' +quotedstr(ssearch);
应该是:
sql.Text := 'Select * FROM tbl_projects where ' + scolumn + ' = ' +quotedstr(ssearch);
第一个QuotedStr使用常规单引号引用列名称,这将引用两个字符串值 - 一个等于列的名称,另一个等于搜索字符串。
如果在列名中使用空格,则应使用适当的字符将其括起来。例如,在MySql中,您应该使用:
sql.Text := 'Select * FROM tbl_projects where `' + scolumn + '` = ' +quotedstr(ssearch);