第二十一章 ActiveX Data Objects 前面第17 章, 筆者已講述Borland Database Engine (簡稱BDE) 模式的資料庫操作, 本章的ActiveX Data Objects(以下簡稱ADO)則是微軟所大力推廣的資料庫存取模式。而Borland 公司的Delphi 及C++Builder 亦支援此模式, 故可以使用ADO 封裝的元件撰寫資料庫程式。ADO 的資料來源元件, 如下圖所示, 其中ADOTable 及ADOQuery 的功能與BDE 的Table 及Query 的用法相近。 ADO與資料聯繫物件 資料庫編輯的方式 主副明細 報表的製作
ADO 與BDE 的關係 前面第16 章, 我們已說明BCB 的資料存取模式共有4 種, 分別是BDE 、ADO 、dbExpress 及InterBase, 其存取模式如下圖所示, 其中BDE 、ADO、dbExpress 及InterBase 稱為資料源元件。 於BDE 模式中, 我們已介紹使用Table 、Query 及QuickRep 等元件展示、查詢、新增、修改、刪除及列印資料庫的內容。本單元則要使用ADO模式, 重複完成以上資料庫的基本操作工作。其次, 由上圖中, 讀者將不難發現, 要使用ADO 模式完成以上資料庫基本操作, 只要將BDE 標籤的元件以ADO 標籤的元件代替即可, 請看以下各節介紹。
2 1 -1 ADO 與資料連繫物件 前面第17-1 節, 我們已使用BDE 模式展示資料庫的內容, 若使用ADO模式, 則只要將BDE 模式的Table 元件以ADO 模式的ADOTable 元件取代即可, 請看以下範例說明。
範例21-1a 請以ADOTable 元件配合資料庫連繫元件, 展示school.mdb 的stugrade 資料表。
2 1 - 2 資料庫編輯的方式 於BDE 模式中, 資料的編輯是使用Table 與Query 元件, 於ADO 模式, 則有ADOTable 與ADOQuery 與之對應。
ADOTable 元件的資料項表示法如下,其中FieldByName 與Fields[欄位索引]應加上型別轉換函式。 ADOTable 與Table 都是一種逐一瀏覽的方式編輯資料庫, 此種資料編輯方式, 本書歸納以下幾個單元, 分別是資料項的表示、記錄指標的移動、記錄的新增、記錄的刪除、記錄的更正、記錄的搜尋及記錄的排序。 資料項 ADOTable 元件的資料項表示法如下,其中FieldByName 與Fields[欄位索引]應加上型別轉換函式。 ADOTable1->FieldValues[" 欄位名稱"] ; ADOTable1->FieldByName(" 欄位名稱")->型別轉換函數; ADOTable1->Fields->Fields[欄位索引]->型別轉換函數;
若已將欄位物件加入欄位編輯器,則亦可使用欄位物件名稱代表某一資料項。例如,以下敘述可存取Name 資料項的內容。 在以上敘述中,型別轉換函式可為AsVariant 、AsString 、AsInteger 、AsFloat 、AsCurrency 、AsDateTime 及AsBoolean 等。如果要將資料項放入Text1 物件,則應加上AsString ,將型別轉換為String 型別。例如,以下敘述可將欄位順序為0 的Name 欄位放入Edit1 物件。 Edit1->Text = ADOTable1->FieldValues["Name"] ; Edit1->Text = ADOTable1->FieldByName("Name")->AsString ; Edit1->Text = ADOTable1->Fields->Fields[0]->AsString ; 若已將欄位物件加入欄位編輯器,則亦可使用欄位物件名稱代表某一資料項。例如,以下敘述可存取Name 資料項的內容。 ADOTable1Name->Value ; // 要注意大小寫 ADOTable1Name->AsString ;
記錄指標 當我們使用ADOTable 物件開啟資料表時, 不管記錄的多寡, 均存在一個稱為記錄指標的東西, 指向資料表的第一筆記錄, 我們稱此記錄為作用中的記錄, 此時若進行資料項的編輯, 則其操作對象即為此記錄指標所指的記錄, 如下圖所示。
範例21-2a 示範各種資料項的用法與記錄指標的移動。
欄位編輯視窗 於表單的資料源元件圖項按二下, 即可出現欄位編輯視窗, 使用者可於欄位編輯視窗新增一些欄位物件。下圖右的ADOTable1name 、ADOTable1chi 及ADOTable1eng 即為新增的欄位物件, 此時即可於程式中使用欄位物件存取資料項, 以下敘述可將ADOTable1name 的內容指定由Edit1顯示。 Edit1->Text=ADOTable1name->AsString ;
範例21-2b 請以欄位物件重做以上範例。
記錄的新增 於資料表中欲新增一筆記錄, 其方法為使用Insert 及Post 方法, 其中Insert 是告訴資料庫即將新增記錄、Post 是將位於記憶體緩衝區的資料回存至資料庫。其中資料項的表示, 本例示範FieldByName (" 欄位名稱") 的使用方式, 讀者可自行使用上一單元所介紹的其它資料項表示法。例如, 以下敘述可分別插入一個字串與一個數值型別的記錄。
以下程式片段, 可於Test1.mdb 的grade 資料表新增一筆記錄。 // 以下敘述使用了型別轉換函數AsStr ing 及AsInteger ADOTable1->Insert() ; // 欄位1 的型別為String ADOTable1->FieldByName(" 欄位名稱1")->AsString = Edit1->Text ; // 欄位2 的型別為Integer ADOTable1->FieldByName(" 欄位名稱2")->AsInteger = StrToInt(Edit2->Text) ; ADOTable1->Post() ; 以下程式片段, 可於Test1.mdb 的grade 資料表新增一筆記錄。 ADOTable1->FieldByName("Name")->AsString = "謝承佑" ; ADOTable1->FieldByName("Chi")->AsInteger = 92 ; ADOTable1->FieldByName("Eng")->AsInteger = 88 ;
範例21-2c 示範記錄的新增(本例使用test1.mdb 的grade 資料表)。
記錄的刪除 刪除記錄的方法是Delete 。其語法如下: 那到底是刪除那一筆記錄呢?答案是刪除記錄指標所指的記錄, 請看以下範例。 ADOTab le 1.De le te ; 那到底是刪除那一筆記錄呢?答案是刪除記錄指標所指的記錄, 請看以下範例。
範例21-2d 示範記錄的刪除(資料表、表單均同上範例)
記錄的更正 記錄的更正是使用Edit 及Post 的方法, 其語法如下: ADOTable1->Post() ; ADOTable1->Edit() ; ADOTable1->FieldByName(" 欄位名稱1")->AsString = Edit1->Text ; ADOTable1->FieldByName(" 欄位名稱2")->AsInteger = StrToInt(Edit2->Text) ; / / 注意型別轉換 ADOTable1->Post() ; 但是如果我們在表單中使用了資料感知元件(例如, DBEdi t),則您只要更改了資料感知元件中的內容,使用以下敘述即可將更改後的內容寫入資料庫中。 以下程式片段可更正grade 資料表的記錄指標所在記錄。 ADOTable1->FieldByName("Name")->AsString = "孫大明" ; ADOTable1->FieldByName("Chi")->AsInteger = 22 ; ADOTable1->FieldByName("Eng")->AsInteger = 33 ;
範例21-2e 示範記錄的更正(資料表同上範例)。 1. 下圖是程式執行結果的初始畫面, 筆者已將記錄指標移至" 朱安琪" 這筆記錄, 右邊的三個DBEdit 元件因是連繫元件的關係, 亦同時顯示" 朱安琪" 的資料。
2. 下圖是按一下" 更正記錄指標的內容", 此按鈕執行以下程式片段, 所 以執行結果, 如下圖所示。 / / - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - / / 更正一筆記錄 void _ _fastcall TForm1::btnEdit1Click(TObject *Sender) { ADOTable1->Edit() ; ADOTable1->FieldByName("Name")->AsString = "謝承佑" ; ADOTable1->FieldByName("Chi")->AsInteger = 92 ; ADOTable1->FieldByName("Eng")->AsInteger = 88 ; ADOTable1->Post() ; }
3. 下圖左是按一下" 更正以上記錄" 的結果, 此按鈕執行以下程式片段,其功能是將連繫物件DBText 的內容回存資料庫。 / / 將連繫元件的結果回存資料庫 void _ _fastcall TForm1::btnEdit2Click(TObject *Sender) { ADOTable1->Post() ; }
4. 下圖右是按一下" 將國文分數加百分之十" 的結果, 此按鈕的程式片段如下: void _ _fastcall TForm1::btnEdit3Click(TObject *Sender) { ADOTable1->First() ; while (! ADOTable1->Eof) { ADOTable1->Edit() ; ADOTable1->FieldByName("Chi")->AsInteger = ADOTable1->FieldByName("Chi")->AsInteger * 1.1 ; ADOTable1->Post() ; ADOTable1->Next() ; }
記錄的搜尋 ADO 模式中記錄的搜尋, 其方法有Locate 及Filter, 分別說明如下: Locate Locate 的語法如下: virtual bool _ _fastcall Locate(const AnsiString KeyFields, const System::Variant &KeyValues, TLocateOptions Options); 以上語法說明如下: KeyFields: 欲搜尋的欄位名稱。 KeyValues: 欲搜尋的欄位值。 Options: 搜尋方式。其型別是TlocateOptions 的集合型別, 如下所示, 其中loCaseInsensitive 是表示搜尋時大小寫不分, loPartialKey 是部份字元符合即可, 例如輸入" 學樂", 若有" 學樂出版社" 或" 學樂出版有限公司", 均符合搜尋條件。 enum TLocateOption {loCaseInsensitive, loPartialKey}; 當搜尋成功時, Locate 函數傳回true, 並將記錄指標移到合乎條件的第一筆記錄; 若傳回false, 則記錄指標並不移動。
範例21-2f 示範記錄的搜尋。
Filter 上一單元的Locate 較適合做字串的搜尋, 若是數值的搜尋, 例如"chi>60" 或"chi<80" 時, 則無法使用Locate, 像這種搜尋某一範圍的動作, 則較適合使用Filter。Filter 的語法如下: ADOTable1->Filter= " 數值欄位名稱關係運算子條件值" ; ADOTable1->Filtered=true ;
範例21-2g 示範Filter 屬性的用法。
排序 ADOTable 元件使用Sort 屬性進行排序, Sort 屬性語法如下, 預設值是升冪ASC, 值得注意的是, ASC 與DESC 一律都必須大寫才行。 ADOTable1->Sort = " 欄位名稱<ASC/DESC>";
範例21-2h 示範Sort 屬性的用法。
ADOQuery 於BDE 模式中, 是使用Query 元件執行SQL 字串, 但是ADO 模式中則使用ADOQuery 。關於SQL 的用法, 本書已分別於17-4 節及19 章介紹, 本單元的ADOQuery 的用法則與Query 相近, 以下範例示範如何使用ADOQuery 展示test1.mdb 的grade 資料表。
範例21-2i 示範ADOQuery 的用法(本例欲以DBGrid 展示test1.mdb 的grade 資料表。
21 - 3 主副明細
ADOConnection 前面的ADOTable 及ADOQuery 均較適合一次開啟一個資料表, 但是有些時候您必須同時開啟兩個資料表, 此時若還是使用ADOTable 或ADOQuery開啟資料庫, 則因要設兩次ConnectionString, 所以您的資料庫將被兩個程式所連接而影響執行速度, 所以若要同時開啟兩個資料表, 則應使用ADOConnection 元件。 以下範例則示範如何使用ADOConnection 元件連結兩個資料表, 以進行主副明細查詢。
範例21-3a 示範主副明細查詢, 主要資料表是test1.mdb 的stuname, 次要資料表是stugrd 。
21 - 4 報表的製作 ADO 報表的製作與BDE 模式的報表製作完全相同, 只要將資料源物件以ADO 標籤的元件替換即可。以下僅以列印test1.mdb 的grade 資料表示範ADO 報表製作, 其餘請自行參考第18 章。
範例21-4a 示範報表的製作。(本例欲列印test1.mdb 的grade 的資料表)