Delphi ADO查询主/详细信息

Delphi ADO查询主/详细信息,delphi,Delphi,如何设置ADOQuery以过滤数据,从而在DBGrid中显示所有有鳟鱼的湖泊 数据: Nate Pond-LakeMaps.Lake_名称 Brook trout - Species.Species_Name Creek chub Golden shiner 黑池 Brook trout Brown bullhead Common shiner Brook trout Brown bullhead Common shiner 普莱西德湖 Lake trout Smallmou

如何设置ADOQuery以过滤数据,从而在DBGrid中显示所有有鳟鱼的湖泊

数据:

Nate Pond-LakeMaps.Lake_名称

Brook trout - Species.Species_Name

Creek chub

Golden shiner
黑池

Brook trout

Brown bullhead

Common shiner
Brook trout

Brown bullhead

Common shiner
普莱西德湖

Lake trout

Smallmouth bass

Yellow perch
MDB数据库

ADoTable1=LakeMapsMASTER

ADOTable2=物种详细信息

关系

LakeMaps Table
LakeMaps.Field[0] = Lake_ID: Autonumber --- ]
LakeMaps.Field[1] = Lake_Name: Text---      |
                                            |Relationship set in the access database
Species Table                               |
Species.Field[0] = Species_ID: numeric ---  ]    
Species.Field[1] = Species_Name: text
物种表是一个细节,湖泊地图是主要的

如何设置ADOQuery以过滤数据,从而在DBGrid中显示所有有鳟鱼的湖泊

过滤数据:

内特池塘

Brook trout

Creek chub

Golden shiner
黑池

Brook trout

Brown bullhead

Common shiner
Brook trout

Brown bullhead

Common shiner

您可以设置
Filtered=true
,然后使用
OnFilterRecord
事件检查详细数据集是否包含请求的值(这可以在循环中完成,也可以使用数据集的
Locate
过程完成)

对于较大数量的数据,这可能会非常缓慢。在这些情况下,我通常直接在SQL中过滤主记录。大概是这样的:

SELECT * FROM LakeMaps 
WHERE Lake_ID in (SELECT Lake_ID 
         FROM Species INNER JOIN SpeciesLakesRelation 
             ON (Species.Species_ID = SpeciesLakesRelation.Species_Id) 
         WHERE SPECIES_NAME = 'Brook Trout')
ADOQuery1.SQL.Add( 'SELECT * FROM LakeMaps WHERE Lake_ID in ' +
  '(SELECT Lake_ID FROM Species INNER JOIN LakeMaps ON ' +
  '(Species.Species_ID = LakeMaps.Lake_Id) ' +
  'WHERE SPECIES_NAME = ' + QuotedStr(ComboBoxSpecies.Text) + ')');
此SQL返回来自具有“布鲁克鳟鱼”的湖泊的记录


SpeciesLakesRelation
是包含湖泊地图和物种之间关系的表格

中查询的问题是,查询中的文本必须使用撇号。如果
ComboBoxSpecies.Text
具有值
Brook Trout
,则SQL的计算结果为:

SELECT * FROM LakeMaps WHERE Lake_ID in 
  (SELECT Lake_ID FROM Species INNER JOIN LakeMaps ON 
     (Species.Species_ID = LakeMaps.Lake_Id) 
   WHERE SPECIES_NAME = Brook Trout)
请注意,Brook Trout并没有撇号,所以您可以从MsAccess获得语法错误

编辑:
正如Gerry在评论中指出的:

  • 应使用
    QuotedStr
    函数添加撇号,而不是双撇号
  • 最好的解决方案是使用查询参数
使用
QuotedStr
的Delphi代码应如下所示:

SELECT * FROM LakeMaps 
WHERE Lake_ID in (SELECT Lake_ID 
         FROM Species INNER JOIN SpeciesLakesRelation 
             ON (Species.Species_ID = SpeciesLakesRelation.Species_Id) 
         WHERE SPECIES_NAME = 'Brook Trout')
ADOQuery1.SQL.Add( 'SELECT * FROM LakeMaps WHERE Lake_ID in ' +
  '(SELECT Lake_ID FROM Species INNER JOIN LakeMaps ON ' +
  '(Species.Species_ID = LakeMaps.Lake_Id) ' +
  'WHERE SPECIES_NAME = ' + QuotedStr(ComboBoxSpecies.Text) + ')');
现在,如果
ComboBoxSpecies.Text
具有值
Brook Trout
,则此字符串:

'WHERE SPECIES_NAME = ' + QuotedStr(ComboBoxSpecies.Text) + ')'
评估为:

WHERE SPECIES_NAME = 'Brook Trout')

这是一个不同于:?谢谢Zendar。。。现在它几乎可以工作了。如何避免登录。我试图从connectionstring中删除“Admin”,但在运行时始终需要登录,即使在Delphi IDE中将所有设置为active?您需要做两件事:在连接字符串中设置用户名和密码,并将TAdoConnection属性LoginPrompt设置为false。如果在ComboBoxSpecies.Text中获得一个带撇号的值,则上述示例将失败。按照上面Fabricio的建议使用QuotedStr,或者更好地使用参数化查询(SQL注入也更安全-如果组合框样式是csDropDownList,可能不会有问题)。