简体   繁体   English

如何使用SQL查询在Delphi中的ADO数据库中搜索字段?

[英]How do I search for a field in an ado database in delphi with a sql query?

I have tried to filter through an ado database table on delphi. 我试图在delphi上筛选一个ado数据库表。

I have a dbgrid connected to the query(qryData), as soon as this code executes then the dbgrid goes blank and nothing further happens. 我有一个连接到查询(qryData)的dbgrid,执行此代码后,dbgrid就会变为空白,并且不再发生任何事情。 Even if I type in a valid field name, it should then display it in the dbgrid but it shows nothing. 即使我输入了有效的字段名,它也应该在dbgrid中显示它,但什么也没显示。 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. 您将需要将对qryData的引用更改为dmUsers.qryData。 Btw, try and avoid using "with ..." 顺便说一句,尝试避免使用“ 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. 请注意,您正在构造的SQL不是理想的,因为它没有考虑要搜索的列是否为数据类型,该数据类型要求查询中指定的值用引号引起来。 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. 您在列名称周围加上引号的事实是网格空白的原因-您在服务器上要求Sql搜索引擎的是所有行,其中“一个字符串” =“另一个字符串”,任何行均为false因此没有返回任何内容。 Btw, this is related to Sql examples you sometimes see which have a where clause like 'where 1 = 2'; 顺便说一句,这与您有时看到的Sql示例有关,其中有一个where子句,例如“ 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. 正如@ mostkito-x所评论的那样,查询原始版本的主要问题之一是查询元素之间缺少空格。请自由使用空格,以便您查看正在执行的操作。 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. 当您遇到查询问题时,可以将其文本放入表单上的备忘录(设置为Courier等固定音调的字体)中也没什么不好的,因此您可以查看一下是否确实在构造查询,以为自己是。

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). 顺便说一句,如果您尚未收集,则在字符串数据类型的搜索值周围使用QuotedStr的优点是可以正确处理搜索值具有嵌入式引号的情况(例如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 ). 同样,使用这种类型的查询还可以了解“ SQL注入”恶意软件的风险( 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. 不幸的是,尽管您可以指定要匹配的列值作为参数,但是您无法在ADO中参数化列

To use a parameterized query, the Sql would look something like 要使用参数化查询,Sql看起来像

Select * from tblProjects where SomeColumn = :somevalue 从tblProjects中选择*,其中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. 然后,在IDE对象检查器中,您需要在qryData上定义一个参数,并在执行查询之前执行qryData.Parameters.ParamByName('somevalue')。Value:= edtSe​​arch.Text。 But, like I said, you can't parameterize the column name to search on. 但是,就像我说的那样,您无法参数化要搜索的列名。

From what I can see the problem is in this line: 从我可以看到的问题在这一行:

sql.Text := 'Select * FROM tbl_projects where' + quotedstr(scolumn) + ' = ' +quotedstr(ssearch);

It should be: 它应该是:

sql.Text := 'Select * FROM tbl_projects where ' + scolumn + ' = ' +quotedstr(ssearch);

The first QuotedStr quotes the column name with regular single quotes, which will compate two string values - one equal to the name of the column, and the other rqual to the search string. 第一个QuotedStr用常规的单引号将列名引起来,这将组成两个字符串值-一个等于列的名称,另一个等于搜索字符串。

If you are using spaces in column names, you should enclose it with appropriate characters. 如果在列名中使用空格,则应使用适当的字符将其括起来。 For example, in MySql you should use: 例如,在MySql中,您应该使用:

sql.Text := 'Select * FROM tbl_projects where `' + scolumn + '` = ' +quotedstr(ssearch);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM