Delphi数据库编程新手指南(09)

数据检索

  数据库应用程序最常见的任务,是根据某些规则来搜索特定的记录。在Delphi中,ADOExpress组件实现检索记录的方法与BDE中的方法类似。本章将引导你学习运用各种方法来搜索和定位数据。

  注:本章涉及到的MS Access数据库—aboutdelphi.mdb,以及核心组件(数据访问和数据感知)的相关设置,请参考课程前些章节。下述示例将假定你的应用程序中,已有一个指向数据库表的ADOTable组件。

  当想到搜索算法,其过程应是:从表的顶部开始,检查每一行的某字段——看它是否符合相关条件,直到遍历完选定的记录或到达底行,停止循环。我们希望Delphi将这些步骤隐藏(封装)起来。ADODataset(Table或Query)组件有几种方法,用于检索及定位数据集中的记录。

定位(Locate

此搜索方法,会把与搜索条件相匹配的当前记录指定为第一行。通过使用Locate方法,能找到已传递给Variant数组的一个或多个字段的值。

下面的代码,通过Locate方法找到第一条Name字段包含'Zoom'的记录。如果返回值为True——表示找到记录,并已置为当前行。

AdoTable1.Locate('Name','Zoom',[]);
{...or...}
 
var ffield, fvalue: string;
    opts : TLocateOptions;        
ffield := 'Name';
fvalue := 'zoom';
opts := [loCaseInsensitive];
if not AdoTable1.Locate(ffield,fvalue, opts) then
  ShowMessage(fvalue + ' not found in ' +ffield);
查询(Lookup

Lookup不会将光标移到匹配行,只返回值。Lookup返回一个variant数组,包含从匹配行返回的指定字段的值——指定字段由一个字段名列表(分号分隔)所指定。如果没找到匹配记录,Lookup返回一个空的variant。

下面代码将返回值赋给名为LookupRes的variant数组:

var LookupRes: Variant;
LookupRes :=ADOTable1.Lookup('Name', 'Zoom', 'Author; Description');
if not VarIsNull(LookupRes)then
 ShowMessage(VarToStr(LookupRes[0])) //authorname

Locate和Lookup方法的一个优势是,他们不需要表进行索引。然而,当一个表拥有索引,Locate方法会用可用的最快的方法来搜索表,因此将会使用索引。

索引(Indexing

索引有助于更快地查找和排序记录。可基於单个或多个字段来创建索引。多字段索引使你能够区分第一个字段可能拥有相同值的记录。多数情况下,你会希望对频繁查找/排序的字段编制索引。例如,若想在Type字段中搜索特定的应用程序类型,可基于此字段创建索引,以加快搜索。

一个表的主键会自动为其编制索引,而数据类型为OLE对象的字段不能编制索引。注意,如果进行索引的字段中具有很多相同的值,编制索引后,检索速度不会有显著的提高。

索引的主要缺点,是其需要占用额外的磁盘空间;在索引列插入、删除和更新数据,比在非索引列上操作需要更长的时间。

当使用Table组件和BDE(不是ADO)时,Delphi为我们提供了一些函数,用于搜索数据库表中的值。如Go、GoToKey、GoToNearest、Find、FindKey,FindNearest等等(完整内容请参阅Delphi的帮助主题)。 ADO不支持这些方法,而是引入了Seek方法。

查找(Seek

ADO数据集的Seek方法进行检索时,需要使用索引。如果没有指定一个索引,在用Access数据库时,数据库引擎将使用主键索引。

Seek基于当前索引查找一个(或多个)指定字段的特定值。如果Seek没有找到所需的行且未发生错误,并到达了数据集的结尾行。表示搜索成功,将返回一个布尔值:如果找到一条记录,则返回True,反之返回False。

TADOTable组件的GetIndexNames方法撷取表中现有索引的列表(例如:组合框里的项目项)。

ADOTable1.GetIndexNames(ComboBox1.Items);

在设计期间,TADOTable组件的IndexName属性提供上面相同的列表。该IndexFieldNames属性可作为指定表的索引的一种替代方法。在“IndexFieldNames”中,指定表索引编制的字段名称。

Seek方法具有以下声明:

function Seek(const KeyValues: Variant; SeekOption: TSeekOption= soFirstEQ): Boolean;

·KeyValues​​是一个值为Variant的数组。一个索引包含一个或多个列,该数组中包含的值分别与对应列进行比较,。

·SeekOption指定KeyValues值与对应列​​之间的比较方式。

SeekOption    含义
soFirstEQ   记录指针定位在第一个匹配的记录上,如果有匹配记录的话,反之定位在该数据集的末尾;
soLastEQ    记录指针定位在最后一个匹配的记录上,如果有匹配记录的话,反之定位在该数据集的末尾;
soAfterEQ   记录指针定位在匹配的记录,如果有匹配记录的话,置于其之后。
soAfter     记录指针定位在匹配的记录之后。
soBeforeEQ  记录指针定位在匹配的记录,如果发现,就在相匹配的记录会被发现。
soBefore    记录指针定位匹配的记录之前会被发现。

注1:Seek方法仅支持服务器端的游标。Seek不支持CursorLocation属性为clUseClient的数据集。使用Supports方法,以确定供应商是否在底层支持Seek。

注2:基于多个字段使用Seek方法时,各字段顺序必须与表结构中的字段顺序相同。否则调用失败。

注3:不能在TADOQuery组件中调用Seek方法。

判断是否找到了匹配记录,我们使用BOF或EOF属性(取决于搜索的方向)。下面代码,在ComboBox中指定索引字段,在EDIT1中指定匹配条件。

var
strIndex: string;
strIndex := ComboBox1.Text;//from the code above
if ADOTable1.Supports(coSeek)then begin
 with ADOTable1 do begin
   Close;
   IndexName := strIndex;
   CursorLocation := clUseServer;
   Open;
   Seek (Edit1.Text, soFirstEQ);
  end;
  if ADOTable1.EOF then
   ShowMessage ('Record value NOT found');
end

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章