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

 

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