版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、第六章 什么是數(shù)據(jù)集Delphi 4中有四種類型的標(biāo)準(zhǔn)數(shù)據(jù)集構(gòu)件,分別是TTable、TQuery、TStoredProc和TClientDataSet。這些數(shù)據(jù)集構(gòu)件都是從一個(gè)共同的基類TDataSet繼承下來(lái)的,其中,只有TClientDataSet是直接從TDataSet繼承下來(lái)的,而TTable、TQuery、TStoredProc的直接上級(jí)是TDBDataSet,TDBDataSet的上級(jí)是TBDEDataSet,TBDEDataSet 的上級(jí)才是TDataSet。這幾個(gè)類之間的繼承關(guān)系可以用圖6.1來(lái)表示。圖6.1 數(shù)據(jù)集的繼承關(guān)系TDataSet是所有數(shù)據(jù)集的抽象基類,它的大部分
2、屬性和方法是虛擬的或抽象的。所謂虛擬的方法,是指這些方法可以被派生類重載。所謂抽象的方法,是指這些方法只有聲明,沒(méi)有定義,派生類必須給出定義后才能調(diào)用這些方法,不同的派生類可以有不同的定義。由于TDataSet中包含抽象的方法,您不能直接創(chuàng)建它的實(shí)例,否則會(huì)引起運(yùn)行期錯(cuò)誤。如果從功能上劃分,TDataSet的屬性和方法可以分為這么幾大塊:打開(kāi)和關(guān)閉數(shù)據(jù)集、瀏覽記錄、編輯數(shù)據(jù)、書(shū)簽管理、控制連接、訪問(wèn)字段、記錄緩沖區(qū)管理、過(guò)濾、事件。6.1 打開(kāi)和關(guān)閉數(shù)據(jù)集在對(duì)數(shù)據(jù)集進(jìn)行任何操作之前,首先要打開(kāi)數(shù)據(jù)集。要打開(kāi)數(shù)據(jù)集,可以把Active屬性設(shè)為T(mén)rue,例如:CustTable.Active :=
3、 True;也可以調(diào)用Open函數(shù),例如:CustQuery.Open;要關(guān)閉數(shù)據(jù)集,可以把Active屬性設(shè)為False或者調(diào)用Close函數(shù)。6.2 數(shù)據(jù)集的狀態(tài)數(shù)據(jù)集的狀態(tài)(State屬性)決定了當(dāng)前能夠?qū)?shù)據(jù)集進(jìn)行的操作,例如,當(dāng)數(shù)據(jù)集已經(jīng)關(guān)閉,它的狀態(tài)是dsInactive,此時(shí)就不能訪問(wèn)數(shù)據(jù)集的任何數(shù)據(jù)。6.2.1 State屬性State屬性是只讀的,下面列出了State屬性可能的值:.dsInactive數(shù)據(jù)集已關(guān)閉,不能訪問(wèn)它的數(shù)據(jù);.dsBrowse數(shù)據(jù)集已打開(kāi),可以瀏覽數(shù)據(jù)但不能修改數(shù)據(jù);.dsEdit此時(shí)為編輯狀態(tài),可以修改數(shù)據(jù);.dsInsert此時(shí)可以插入一條新的記
4、錄;.dsSetKey只適用于TTable和TClientDataSet,此時(shí)可以設(shè)置范圍和鍵值,并且可以調(diào)用GotoKey函數(shù);.dsCalcFields正在處理OnCalcFields事件(當(dāng)字段需要指定一個(gè)值的時(shí)候促發(fā)的事件),此時(shí)不能修改非計(jì)算字段的值;.dsCurValue內(nèi)部使用;.dsNewValue內(nèi)部使用;.dsOldValue內(nèi)部使用;.dsFilter正在進(jìn)行過(guò)濾操作。當(dāng)一個(gè)數(shù)據(jù)集剛剛打開(kāi)的時(shí)候,它的State屬性被設(shè)為dsBrowse,以后,State屬性的值會(huì)隨著應(yīng)用程序的操作自動(dòng)變化。要使數(shù)據(jù)集進(jìn)入dsBrowse、dsEdit、dsInsert或dsSetKey狀
5、態(tài),就得調(diào)用相應(yīng)的方法。 例如,要使數(shù)據(jù)集CustTable進(jìn)入dsInsert狀態(tài),程序示例如下:Procedure TForm1.InsertButtonClick(Sender: TObject);BeginCustTable.Insert;進(jìn)入dsInsert狀態(tài)AddressPromptDialog.ShowModal;If AddressPromptDialog.ModalResult := mrOK thenCustTable.Post; 恢復(fù)為dsBrowse狀態(tài)ElseCustTable.Cancel; 恢復(fù)為dsBrowse狀態(tài)End;從上面這個(gè)例子可以看出,有些操作會(huì)使數(shù)
6、據(jù)集自動(dòng)變成dsBrowse狀態(tài),例如,調(diào)用Post函數(shù)如果成功的話,數(shù)據(jù)集就恢復(fù)為dsBrowse狀態(tài),如果調(diào)用Post沒(méi)有成功,數(shù)據(jù)集仍然保持原來(lái)的狀態(tài)。調(diào)用Cancel也能使數(shù)據(jù)集恢復(fù)為dsBrowse狀態(tài)。如果把Active屬性設(shè)為False,或者調(diào)用Close,將使數(shù)據(jù)集進(jìn)入dsInactive狀態(tài)。例如,下面兩行代碼是等價(jià)的:CustTable.Active := False;CustTable.Close;有些狀態(tài)如dsCalcFields、dsCurValue、dsNewValue、dsOldValue和dsFilter不能被應(yīng)用程序所控制,而是由數(shù)據(jù)集本身根據(jù)需要自動(dòng)設(shè)置的。
7、例如,當(dāng)正在處理OnCalcFields事件時(shí),就自動(dòng)進(jìn)入dsCalcFields狀態(tài)。當(dāng)退出處理OnCalcFields事件的句柄時(shí),數(shù)據(jù)集自動(dòng)恢復(fù)成原先的狀態(tài)。當(dāng)數(shù)據(jù)集的狀態(tài)發(fā)生改變時(shí),會(huì)觸發(fā)TDataSource構(gòu)件的OnStateChange事件,如果這個(gè)TDataSource構(gòu)件的DataSet屬性指定了這個(gè)數(shù)據(jù)集的話。下面詳細(xì)介紹數(shù)據(jù)集的各種狀態(tài)以及怎樣進(jìn)入這些狀態(tài)。6.2.2 dsInactive狀態(tài)當(dāng)數(shù)據(jù)集已關(guān)閉時(shí),就處于dsInactive狀態(tài)。此時(shí),不能訪問(wèn)它的任何數(shù)據(jù)。要使數(shù)據(jù)集進(jìn)入dsInactive狀態(tài),可以把Active屬性設(shè)為False,或者調(diào)用Close。在數(shù)據(jù)
8、集將要關(guān)閉之前,會(huì)觸發(fā)BeforeClose事件。當(dāng)數(shù)據(jù)集剛剛關(guān)閉,會(huì)觸發(fā)AfterClose事件。如果在數(shù)據(jù)集處于dsEdit或dsInsert狀態(tài)時(shí)調(diào)用Close,應(yīng)當(dāng)在處理BeforeClose事件的句柄中提示用戶是認(rèn)可還是取消。程序示例如下:Procedure CustTable.VerifyBeforeClose(DataSet: TDataSet)BeginIf (CustTable.State = dsEdit) or (CustTable.State = dsInsert) thenBeginIf MessageDlg(認(rèn)可修改嗎?, mtConfirmation, mbYes
9、No, 0) = mrYes thenCustTable.Post;ElseCustTable.Cancel;End;End;6.2.3 dsBrowse狀態(tài)當(dāng)一個(gè)數(shù)據(jù)集剛剛打開(kāi)的時(shí)候,數(shù)據(jù)集總是處于dsBrowse狀態(tài),此時(shí),可以顯示數(shù)據(jù)集中的記錄,但不能編輯和插入記錄。dsBrowse狀態(tài)可以認(rèn)為是數(shù)據(jù)集的基本狀態(tài),在此狀態(tài)下,可以進(jìn)入其他狀態(tài)。例如,調(diào)用Insert或Append函數(shù)將使數(shù)據(jù)集的狀態(tài)從dsBrowse變成dsInsert(當(dāng)然,這還取決于其他因素,如CanModify屬性的值),調(diào)用SetKey將使數(shù)據(jù)集從dsBrowse變成dsSetKey狀態(tài)。TDataSet有兩個(gè)方
10、法可以使數(shù)據(jù)集回到dsBrowse狀態(tài),一個(gè)是Cancel,它將取消當(dāng)前正在進(jìn)行的編輯、插入、搜索等操作,使數(shù)據(jù)集回到dsBrowse狀態(tài)。另一個(gè)是Post,它將試圖把修改了的數(shù)據(jù)保存到數(shù)據(jù)集中,如果成功的話,數(shù)據(jù)集將回到dsBrowse狀態(tài),如果沒(méi)有成功,數(shù)據(jù)集仍然保持原先的狀態(tài)。6.2.4 dsEdit狀態(tài)如果應(yīng)用程序要修改數(shù)據(jù)集的數(shù)據(jù),必須首先進(jìn)入dsEdit狀態(tài)。要進(jìn)入dsEdit狀態(tài),可以調(diào)用Edit。不過(guò),調(diào)用Edit并不能保證一定能進(jìn)入dsEdit狀態(tài),這還取決于CanModify屬性的值。如果這個(gè)屬性返回True的話,表示數(shù)據(jù)集是可以讀和寫(xiě)的。對(duì)于TTable構(gòu)件來(lái)說(shuō),如果Re
11、adOnly屬性設(shè)為T(mén)rue,CanModify屬性肯定返回False。對(duì)于TQuery構(gòu)件來(lái)說(shuō),如果RequestLive屬性設(shè)為False,CanModify屬性肯定返回False。即使數(shù)據(jù)集進(jìn)入了dsEdit狀態(tài),也并不意味著用戶就一定能修改數(shù)據(jù),數(shù)據(jù)控件的ReadOnly屬性還必須設(shè)為False。此外,對(duì)于SQL數(shù)據(jù)庫(kù)來(lái)說(shuō),用戶能不能修改數(shù)據(jù)還取決于用戶有沒(méi)有修改數(shù)據(jù)的權(quán)限。要從dsEdit狀態(tài)返回到dsBrowse狀態(tài),可以調(diào)用Cancel、Post或Delete函數(shù),其中,如果Post和Delete沒(méi)有調(diào)用成功的話,就仍然保持dsEdit狀態(tài)。在數(shù)據(jù)控件中,當(dāng)用戶修改了數(shù)據(jù)后把輸入
12、焦點(diǎn)移走,就相當(dāng)于調(diào)用Post函數(shù),將使數(shù)據(jù)集回到dsBrowse狀態(tài)。6.2.5 dsInsert狀態(tài)如果應(yīng)用程序要插入新的記錄,必須首先進(jìn)入dsInsert狀態(tài)。要進(jìn)入dsInsert狀態(tài),可以調(diào)用Insert或Append函數(shù)。不過(guò),調(diào)用Insert或Append并不能保證一定能進(jìn)入dsInsert狀態(tài),這還取決于CanModify屬性的值是否返回True。即使數(shù)據(jù)集進(jìn)入了dsInsert狀態(tài),也并不意味著用戶就一定能插入記錄,數(shù)據(jù)控件的ReadOnly屬性還必須設(shè)為False。此外,對(duì)于SQL數(shù)據(jù)庫(kù)來(lái)說(shuō),用戶能不能插入記錄還取決于用戶有沒(méi)有修改數(shù)據(jù)的權(quán)限。要從dsInsert狀態(tài)返回到
13、dsBrowse狀態(tài),可以調(diào)用Cancel、Post或Delete函數(shù),其中,如果Post沒(méi)有調(diào)用成功的話,就仍然保持dsInsert狀態(tài)。在數(shù)據(jù)控件中,當(dāng)用戶修改了數(shù)據(jù)后把輸入焦點(diǎn)移走,就相當(dāng)于調(diào)用Post,將使數(shù)據(jù)集回到dsBrowse狀態(tài)。6.2.6 dsSetKey狀態(tài)可以調(diào)用Locate、Lookup在數(shù)據(jù)集中搜索特定的記錄。對(duì)于TTable構(gòu)件來(lái)說(shuō),還可以調(diào)用GotoKey、GotoNearest、FindKey或FindNearest在表格中搜索特定的記錄。在調(diào)用上述方法之前,必須首先使數(shù)據(jù)集進(jìn)入dsSetKey狀態(tài)。要使數(shù)據(jù)集進(jìn)入dsSetKey狀態(tài),可以調(diào)用SetKey。調(diào)用
14、了上述方法后,數(shù)據(jù)集又回到dsBrowse狀態(tài)。另外,可以對(duì)數(shù)據(jù)集進(jìn)行過(guò)濾。對(duì)于TTable構(gòu)件來(lái)說(shuō),還可以預(yù)先設(shè)置范圍。在進(jìn)行過(guò)濾和范圍操作前,也要首先進(jìn)入dsSetKey狀態(tài)。6.2.7 dsCalcFields狀態(tài)當(dāng)OnCalcFields事件被觸發(fā)時(shí),就會(huì)使數(shù)據(jù)集進(jìn)入dsCalcFields狀態(tài)。在處理OnCalcFields事件的句柄中,應(yīng)當(dāng)給出“計(jì)算字段”的值。在dsCalcFields狀態(tài)下,除了“計(jì)算字段”外,應(yīng)用程序不能修改其他字段的值,因?yàn)槿绻渌侄蔚闹蛋l(fā)生變化,又會(huì)導(dǎo)致OnCalcFields事件被觸發(fā),從而導(dǎo)致無(wú)限循環(huán)。當(dāng)OnCalcFields事件處理完畢,數(shù)據(jù)集又
15、回到dsBrowse狀態(tài)。6.2.8 dsFilter狀態(tài)當(dāng)OnFilterRecord事件被觸發(fā)時(shí),就會(huì)使數(shù)據(jù)集進(jìn)入dsFilter狀態(tài)。在此狀態(tài)下,不允許修改數(shù)據(jù)集的記錄,否則,過(guò)濾就無(wú)法正確執(zhí)行。當(dāng)OnFilterRecord事件處理完畢,數(shù)據(jù)集就回到dsBrowse狀態(tài)。6.2.9 dsNewValue、dsOldValue或dsCurValue在允許緩存更新的情況下,當(dāng)用戶修改數(shù)據(jù)集的記錄時(shí),數(shù)據(jù)集有可能會(huì)進(jìn)入dsNewValue、dsOldValue或dsCurValue狀態(tài)。在這三種狀態(tài)下,可以通過(guò)字段(TField)的NewValue、OldValue或CurValue屬性來(lái)訪
16、問(wèn)當(dāng)時(shí)的值。上述三個(gè)狀態(tài)是由Delphi 4內(nèi)部使用的,應(yīng)用程序無(wú)法主動(dòng)進(jìn)入上述三種狀態(tài)。6.3 瀏 覽 記 錄每個(gè)活動(dòng)的數(shù)據(jù)集都有一個(gè)指針,指向當(dāng)前記錄。很多對(duì)數(shù)據(jù)集的操作都是針對(duì)當(dāng)前記錄,許多數(shù)據(jù)控件也只顯示當(dāng)前記錄的數(shù)據(jù),因此,在數(shù)據(jù)庫(kù)應(yīng)用程序中知道當(dāng)前記錄的位置是非常重要的。數(shù)據(jù)庫(kù)應(yīng)用程序往往要改變當(dāng)前記錄的位置,這時(shí)候就要用到下面這些方法:.First使第一條記錄成為當(dāng)前記錄;.Last使最后一條記錄成為當(dāng)前記錄;.Next使下一條記錄成為當(dāng)前記錄;.Prior使前一條記錄成為當(dāng)前記錄;.MoveBy使距離當(dāng)前記錄若干行的記錄成為當(dāng)前記錄。此外,Delphi 4中有一個(gè)TDBNavi
17、gator構(gòu)件,專門(mén)用來(lái)瀏覽記錄,它把上述方法用按鈕來(lái)實(shí)現(xiàn)。除了上述方法外,TDataSet中還有兩個(gè)只讀的布爾類型的屬性用來(lái)判斷當(dāng)前記錄的位置,一個(gè)是Bof,如果這個(gè)屬性返回True,表示現(xiàn)在已到了數(shù)據(jù)集的開(kāi)始位置。另一個(gè)是Eof,如果這個(gè)屬性返回True,表示現(xiàn)在已到了數(shù)據(jù)集的末尾。6.3.1 First和Last調(diào)用First函數(shù)能夠使數(shù)據(jù)集的第一條記錄成為當(dāng)前記錄,并且把Bof屬性設(shè)為T(mén)rue。如果第一條記錄已經(jīng)是當(dāng)前記錄了,F(xiàn)irst就什么也不干。程序示例如下:CustTable.First;調(diào)用Last函數(shù)能夠使數(shù)據(jù)集的最后一條記錄成為當(dāng)前記錄,并且把Eof屬性設(shè)為T(mén)rue。如果最
18、后一條記錄已經(jīng)是當(dāng)前記錄,Last就什么也不干。程序示例如下:CustTable.Last;用TDBNavigator構(gòu)件實(shí)現(xiàn)的導(dǎo)航器上有兩個(gè)按鈕,分別對(duì)應(yīng)著First和Last。6.3.2 Next和Prior調(diào)用Next函數(shù)能夠使下一條記錄成為當(dāng)前記錄。如果當(dāng)前記錄已經(jīng)是數(shù)據(jù)集的最后一條記錄,Next就什么也不干。程序示例如下:CustTable.Next;調(diào)用Prior能夠使前一條記錄成為當(dāng)前記錄。如果當(dāng)前記錄已經(jīng)是數(shù)據(jù)集的第一條記錄,Prior就什么也不干。程序示例如下:CustTable.Prior; 6.3.3 MoveBy調(diào)用MoveBy函數(shù)使數(shù)據(jù)集中的另一條記錄成為當(dāng)前記錄,該
19、記錄距原先的當(dāng)前記錄若干行。MoveBy需要傳遞一個(gè)參數(shù),指定相隔的行數(shù),正數(shù)表示向記錄編號(hào)增大的方向移動(dòng),負(fù)數(shù)表示向記錄編號(hào)減小的方向移動(dòng)。程序示例如下:CustTable.MoveBy(-2);MoveBy返回實(shí)際移動(dòng)的行數(shù),返回值與傳遞給MoveBy的參數(shù)有可能不同。注意:在多用戶環(huán)境下,其他用戶有可能正在修改、插入或刪除記錄,這樣,一條記錄原來(lái)距當(dāng)前記錄是5行,現(xiàn)在有可能變?yōu)?行和6行,甚至該記錄都不存在了,因?yàn)槠渌脩粜薷脑撚涗浀臄?shù)據(jù)或刪除了該記錄。6.3.4 Eof和Bof屬性TDataSet有兩個(gè)只讀的屬性Eof和Bof,分別用于判斷是否到了數(shù)據(jù)集的末尾和開(kāi)頭。在遍歷數(shù)據(jù)集的所有
20、記錄時(shí)經(jīng)常要用到這兩個(gè)屬性。如果Eof屬性返回True,表示現(xiàn)在已到了數(shù)據(jù)集的末尾。進(jìn)行下列操作時(shí)會(huì)把Eof屬性設(shè)為T(mén)rue:.打開(kāi)一個(gè)空的數(shù)據(jù)集;.調(diào)用了Last;.調(diào)用了Next,而現(xiàn)在已經(jīng)在數(shù)據(jù)集的最后一條記錄;.調(diào)用了SetRange,而范圍是無(wú)效的。除了上述情況外,Eof屬性都將返回False。Eof屬性通常用在一個(gè)循環(huán)中,每調(diào)用一次Next就要判斷一下Eof屬性,以避免對(duì)不存在的記錄進(jìn)行操作。程序示例如下:CustTable.DisableControls;TryCustTable.First;While not CustTable.EOF DoBegin.CustTable.Ne
21、xt;End;FinallyCustTable.EnableControls;End;上述代碼同時(shí)演示了在遍歷數(shù)據(jù)集的所有記錄時(shí)怎樣暫時(shí)禁止數(shù)據(jù)控件跟著刷新。在遍歷數(shù)據(jù)集的所有記錄前應(yīng)當(dāng)調(diào)用DisableControls禁止刷新,這樣能夠加快遍歷的速度,因?yàn)樗⑿乱彩且〞r(shí)間的。遍歷結(jié)束后,應(yīng)當(dāng)調(diào)用EnableControls恢復(fù)刷新。EnableControls最好在Try.Finally結(jié)構(gòu)的Finally部分調(diào)用,這樣能保證即使在遍歷時(shí)出現(xiàn)異常,也能保證刷新能得到恢復(fù)。 如果Bof屬性返回True,表示現(xiàn)在已到了數(shù)據(jù)集的開(kāi)頭。進(jìn)行下列操作時(shí)會(huì)把Bof屬性設(shè)為T(mén)rue:.打開(kāi)一個(gè)非空的數(shù)據(jù)集
22、;.調(diào)用了First;.調(diào)用了Prior,而現(xiàn)在已經(jīng)在數(shù)據(jù)集的第一條記錄。除了上述情況外,Bof屬性都將返回False。與Eof屬性一樣,Bof屬性通常用在一個(gè)循環(huán)中,每調(diào)用一次Prior就要判斷一下Bof屬性,以避免對(duì)不存在的記錄進(jìn)行操作。程序示例如下:CustTable.DisableControls;TryWhile not CustTable.BOF DoBegin.CustTable.Prior;End;FinallyCustTable.EnableControls;End;6.4 書(shū) 簽書(shū)簽的作用是在數(shù)據(jù)集的某個(gè)位置做一個(gè)標(biāo)記,以后可以快速方便地回到那個(gè)位置。TDataSet中提供
23、了若干個(gè)屬性和方法用于管理書(shū)簽。如果讀Bookmark屬性,返回當(dāng)前記錄的書(shū)簽。如果寫(xiě)B(tài)ookmark屬性,它能使一個(gè)指定的書(shū)簽成為當(dāng)前書(shū)簽。TDataSet中有關(guān)書(shū)簽的幾個(gè)函數(shù)都是虛擬的,TDataSet的派生類TBDEDataSet重新定義了這些方法,包括:.BookmarkValid判斷某個(gè)書(shū)簽是否合法;.CompareBookmarks比較兩個(gè)書(shū)簽是否相同;.GetBookmark創(chuàng)建一個(gè)書(shū)簽來(lái)標(biāo)記當(dāng)前記錄;.GotoBookmark回到用GetBookmark標(biāo)記的位置;.FreeBookmark刪除一個(gè)書(shū)簽。要?jiǎng)?chuàng)建一個(gè)書(shū)簽,首先要聲明一個(gè)TBookmark類型的變量,然后調(diào)用Get
24、Bookmark函數(shù)創(chuàng)建一個(gè)標(biāo)記當(dāng)前記錄的書(shū)簽。TBookmark類型的變量實(shí)際上是一個(gè)無(wú)類型的指針。在調(diào)用GotoBookmark之前,最好先調(diào)用BookmarkValid判斷書(shū)簽是否合法,因?yàn)闀?shū)簽標(biāo)記的記錄有可能已刪掉。如果BookmarkValid返回True,說(shuō)明書(shū)簽是合法的,可以調(diào)用GotoBookmark跳轉(zhuǎn)到書(shū)簽標(biāo)記的位置??梢哉{(diào)用CompareBookmarks比較兩個(gè)書(shū)簽是否相同,如果兩個(gè)書(shū)簽不同,這個(gè)函數(shù)就返回1。如果兩個(gè)書(shū)簽相同或者都是NIL,這個(gè)函數(shù)就返回0。GotoBookmark需要傳遞一個(gè)參數(shù),即書(shū)簽。FreeBookmark用于刪除一個(gè)書(shū)簽。當(dāng)一個(gè)書(shū)簽已用不到時(shí)
25、,應(yīng)當(dāng)及時(shí)刪除它,因?yàn)闀?shū)簽也是一種資源。下面這段代碼演示了書(shū)簽的用法:Procedure DoSomething (const Tbl: TTable)varBookmark: TBookmark;BeginBookmark := Tbl.GetBookmark;Tbl.DisableControls;TryTbl.First;While not Tbl.EOF DoBegin.Tbl.Next;End;FinallyTbl.GotoBookmark(Bookmark);Tbl.EnableControls;Tbl.FreeBookmark(Bookmark); End;End;6.5 搜索特
26、定的記錄可以調(diào)用Locate和Lookup函數(shù)在數(shù)據(jù)集中搜索特定的記錄。 Locate用于在數(shù)據(jù)集中定位一條特定的記錄,并使該記錄成為當(dāng)前記錄。Locate需要傳遞三個(gè)參數(shù),第一個(gè)是KeyFields參數(shù),用于指定要按哪些字段搜索,第二個(gè)是KeyValues參數(shù),用于指定每個(gè)字段相應(yīng)的值,第三個(gè)是Options參數(shù),用于設(shè)置搜索選項(xiàng)。下面這個(gè)例子搜索Company字段的值為“Professional Ltd.”的記錄:varLocateSuccess: Boolean;SearchOptions: TLocateOptions;BeginSearchOptions := loPartialKe
27、y;LocateSuccess := CustTable.Locate(Company, Professional Ltd.,SearchOptions);End;如果Locate找到了一條符合條件的記錄,就把該記錄變?yōu)楫?dāng)前記錄,并返回True。如果Locate沒(méi)有找到匹配的記錄,就返回False。 對(duì)于Locate來(lái)說(shuō),KeyFields參數(shù)指定的字段越多,搜索的條件就越精確。如果KeyFields參數(shù)需要指定多個(gè)字段,彼此之間要用分號(hào)分開(kāi)。由于字段的數(shù)據(jù)類型可能各不相同,因此,KeyValues是一個(gè)Variant類型的參數(shù)。如果KeyFields參數(shù)指定了多個(gè)字段,KeyValues參數(shù)
28、必須是一個(gè)可變類型的數(shù)組。程序示例如下:With CustTable Do Locate(Company;Contact;Phone, VarArrayOf(Sight Diver,P), loPartialKey); Lookup與Locate非常相似,也是在數(shù)據(jù)集中搜索特定的記錄。不同的是,如果找到匹配的記錄,Lookup能返回該記錄中若干個(gè)字段的值。 Lookup需要傳遞三個(gè)參數(shù),第一個(gè)是KeyFields參數(shù),用于指定要按哪些字段搜索,第二個(gè)是KeyValues參數(shù),用于指定每個(gè)字段相應(yīng)的值,第三個(gè)是ResultFields參數(shù),用于指定要返回哪些字段的值。下面這個(gè)例子在CustTab
29、le中搜索Company字段的值為“Professional Ltd.”的記錄,并返回Company、Contact、Phone等字段的值:varLookupResults: Variant;BeginWith CustTable DoLookupResults := Lookup(Company, Professional Divers, Ltd., Company;Contact; Phone);End;如果ResultFields參數(shù)指定了多個(gè)字段,Lookup返回一個(gè)可變類型的數(shù)組。如果沒(méi)有找到匹配的記錄,Lookup將返回一個(gè)空的數(shù)組。程序示例如下: varLookupResults
30、: Variant;BeginWith CustTable DoLookupResults := Lookup(Company; City, VarArrayOf(Sight Diver, Christiansted), Company; Addr1; Addr2; State; Zip);End;6.6 過(guò) 濾一個(gè)應(yīng)用程序往往只對(duì)數(shù)據(jù)集的部分記錄感興趣,例如,可能只對(duì)一個(gè)客戶表中來(lái)自廣東的客戶感興趣。這種情況下,可以用過(guò)濾技術(shù)把符合特定條件的記錄過(guò)濾出來(lái)。不過(guò),對(duì)于一個(gè)字段很多的數(shù)據(jù)集來(lái)說(shuō),最好還是使用查詢。6.6.1 允許過(guò)濾要對(duì)數(shù)據(jù)集進(jìn)行過(guò)濾,首先要指定過(guò)濾條件,并設(shè)置FilterOpt
31、ions屬性設(shè)置有關(guān)選項(xiàng)(可選),然后把Filtered屬性設(shè)為T(mén)rue。以后如果不想進(jìn)行過(guò)濾,只要把Filtered屬性設(shè)為False。要指定過(guò)濾條件有兩種方式:一是設(shè)置Filter屬性,二是在處理OnFilterRecord事件的句柄中給出過(guò)濾條件。Filter屬性適合于在運(yùn)行期使用,它能夠動(dòng)態(tài)地指定過(guò)濾條件,能夠根據(jù)需要改變過(guò)濾條件。不過(guò),F(xiàn)ilter屬性是一個(gè)字符串,過(guò)濾條件相對(duì)比較簡(jiǎn)單。雖然可以用運(yùn)算符構(gòu)成復(fù)合的條件表達(dá)式,但只限于幾個(gè)常見(jiàn)的運(yùn)算符。更主要的是,用Filter屬性指定的表達(dá)式中只能出現(xiàn)數(shù)據(jù)集中已有的字段名和常量,不能出現(xiàn)其他數(shù)據(jù)。而OnFilterRecord事件則靈
32、活得多,它能夠在設(shè)計(jì)期就指定好過(guò)濾條件。而在處理OnFilterRecord事件的句柄中,可以任意指定過(guò)濾條件,過(guò)濾條件可以很復(fù)雜。6.6.2 Filter屬性Filter屬性是一個(gè)字符串,可以這樣設(shè)置Filter屬性:Dataset1.Filter := State = CA;也可以這樣設(shè)置Filter屬性:Dataset1.Filter := Edit1.Text;上面這行代碼允許讓用戶自己輸入過(guò)濾條件。甚至還可以把上述兩行代碼結(jié)合起來(lái):Dataset1.Filter := State = + Edit1.Text;設(shè)置了過(guò)濾條件后,只要把Filtered屬性設(shè)為T(mén)rue,過(guò)濾即有效。可以
33、用比較和邏輯運(yùn)算符構(gòu)造復(fù)合的過(guò)濾條件,這些運(yùn)算符包括:. <小于;. >大于;. >=大于等于;. <=小于等于;.=等于;. <>不等于;.AND兩邊的表達(dá)式都必須為T(mén)rue;.NOT表達(dá)式不能為T(mén)rue;.OR兩個(gè)表達(dá)式只要有一個(gè)為T(mén)rue。下面這個(gè)例子用AND運(yùn)算符限制CustNo字段必須大于1400且小于1500:(CustNo > 1400) AND (CustNo < 1500);注意:在Filtered屬性設(shè)為T(mén)rue的情況下,用戶修改、插入的記錄有可能不符合過(guò)濾的條件,這時(shí)候,會(huì)拒絕接受與過(guò)濾條件矛盾的記錄。6.6.3 OnFil
34、terRecord事件在Filtered屬性設(shè)為T(mén)rue的情況下,數(shù)據(jù)集中的每條記錄都會(huì)觸發(fā)OnFilterRecord事件,這樣,就有機(jī)會(huì)決定是否要把記錄過(guò)濾。處理OnFilterRecord事件的句柄中有一個(gè)布爾類型的Accept參數(shù),把這個(gè)參數(shù)設(shè)為T(mén)rue表示接受此記錄,把這個(gè)參數(shù)設(shè)為False表示把此記錄過(guò)濾掉。程序示例如下:Procedure TForm1.Table1FilterRecord(DataSet: TDataSet; var Accept: Boolean);BeginAccept := DataSetState = CA;End;上面這個(gè)例子的意思是,只有State字
35、段的值為CA的記錄才被接受。注意:由于數(shù)據(jù)集的每條記錄都會(huì)觸發(fā)OnFilterRecord事件,因此,處理OnFilterRecord事件的代碼要盡可能地簡(jiǎn)短,尤其是對(duì)一個(gè)有很多條記錄的大型數(shù)據(jù)集。有時(shí)候,程序需要按多種不同的過(guò)濾條件進(jìn)行過(guò)濾,可以建立多個(gè)處理OnFilterRecord事件的句柄,然后在運(yùn)行期動(dòng)態(tài)地切換事件句柄,程序示例如下:DataSet1.OnFilterRecord := NewYorkFilter;Refresh;6.6.4 設(shè)置過(guò)濾選項(xiàng)FilterOptions屬性用于設(shè)置過(guò)濾的選項(xiàng)。這個(gè)屬性是一個(gè)集合,可以是空集(默認(rèn)),也可以包含下列元素:.foCaseInse
36、nsitive比較字符串時(shí)忽略大小寫(xiě);.foPartialCompare對(duì)于字符串類型的字段必須全字匹配,不允許部分匹配。例如,為了在比較State字段時(shí)忽略大小寫(xiě),可以這樣設(shè)置:FilterOptions := foCaseInsensitive;Filter := State = CA; 6.6.5 在過(guò)濾后的數(shù)據(jù)集中瀏覽記錄過(guò)濾后的數(shù)據(jù)集實(shí)際上是原來(lái)的數(shù)據(jù)集的一個(gè)子集。TDataSet提供了四個(gè)方法用于在過(guò)濾后的數(shù)據(jù)集中瀏覽記錄,它們是:.FindFirst使過(guò)濾后的數(shù)據(jù)集中的第一條記錄成為當(dāng)前記錄;.FindLast使過(guò)濾后的數(shù)據(jù)集中的最后一條記錄成為當(dāng)前記錄;.FindNext使過(guò)濾
37、后的數(shù)據(jù)集中的下一條記錄成為當(dāng)前記錄;.FindPrior使過(guò)濾后的數(shù)據(jù)集中的前一條記錄成為當(dāng)前記錄。上述四個(gè)方法如果調(diào)用成功,就返回True,否則,就返回False??梢詸z查一個(gè)只讀的Found屬性,看看上次調(diào)用是否成功。如果通過(guò)Filter屬性或OnFilterRecord事件設(shè)置了過(guò)濾條件,而Filtered屬性設(shè)為False,調(diào)用上述四個(gè)方法時(shí)會(huì)自動(dòng)暫時(shí)允許過(guò)濾,然后移動(dòng)當(dāng)前記錄的位置,最后又禁止過(guò)濾。換句話說(shuō),上述四個(gè)方法可以不理會(huì)Filtered屬性是怎樣設(shè)置的。如果沒(méi)有設(shè)置過(guò)濾條件,上述四個(gè)方法即相當(dāng)于First、Last、Next和Prior。6.7 修 改 數(shù) 據(jù)TDataS
38、et中提供了一些方法用于在數(shù)據(jù)集中更新、插入和刪除記錄,它們是:.Edit使數(shù)據(jù)集進(jìn)入dsEdit狀態(tài);.Append在數(shù)據(jù)集的末尾添加一條記錄;.Insert在數(shù)據(jù)集的當(dāng)前位置插入一條記錄;.Post試圖把用戶對(duì)數(shù)據(jù)的修改寫(xiě)到數(shù)據(jù)集中;.Cancel取消用戶對(duì)數(shù)據(jù)的修改,使數(shù)據(jù)集回到dsBrowse狀態(tài);.Delete刪除當(dāng)前記錄。6.7.1 進(jìn)入dsEdit狀態(tài)要編輯數(shù)據(jù)集的記錄,首先要進(jìn)入dsEdit狀態(tài)。要進(jìn)入dsEdit狀態(tài),調(diào)用Edit函數(shù)。不過(guò),調(diào)用Edit不一定會(huì)使數(shù)據(jù)集進(jìn)入dsEdit狀態(tài),還取決于CanModify屬性的值。一旦數(shù)據(jù)集進(jìn)入了dsEdit狀態(tài),用戶就可以在數(shù)據(jù)
39、控件上修改當(dāng)前記錄的值。當(dāng)用戶把輸入焦點(diǎn)從當(dāng)前記錄上移走,即相當(dāng)于調(diào)用了Post函數(shù)。程序示例如下:With CustTable DoBeginEdit;FieldValuesCustNo := 1234;Post;End;要取消當(dāng)前未決的修改,用戶可以按ESC鍵或單擊用TDBNavigator構(gòu)件實(shí)現(xiàn)的導(dǎo)航器上的Cancel按鈕。在使用緩存更新技術(shù)(CachedUpdates屬性設(shè)為T(mén)rue)的情況下,調(diào)用Post只是把數(shù)據(jù)寫(xiě)到緩存中,而不是直接寫(xiě)到數(shù)據(jù)集中。要把緩存中的數(shù)據(jù)寫(xiě)到數(shù)據(jù)集中,需調(diào)用ApplyUpdates函數(shù)。6.7.2 插入新的記錄要在數(shù)據(jù)集中插入新的記錄,首先要進(jìn)入dsIn
40、sert狀態(tài)。要進(jìn)入dsInsert狀態(tài),可以調(diào)用Insert或Append函數(shù)。不過(guò),調(diào)用Insert或Append不一定會(huì)使數(shù)據(jù)集進(jìn)入dsInsert狀態(tài),還取決于CanModify屬性的值。一旦進(jìn)入了dsInsert狀態(tài),用戶就可以在數(shù)據(jù)控件(一般是TDBGrid)中插入一條新的記錄,并給這條記錄輸入數(shù)據(jù)。如果要通過(guò)編程來(lái)插入新的記錄,就要注意Insert和Append的區(qū)別。Insert將把一條新的記錄插入到當(dāng)前記錄的前面,而Append將把一條新的記錄添加到數(shù)據(jù)集的末尾。插入了新的記錄后,應(yīng)當(dāng)調(diào)用Post或在CachedUpdates屬性設(shè)為T(mén)rue的情況下調(diào)用ApplyUpdate
41、s把新的記錄寫(xiě)到數(shù)據(jù)集中。如果數(shù)據(jù)集是已建立了索引的Paradox或dBASE表,新記錄將自動(dòng)移到恰當(dāng)?shù)奈恢谩H绻麛?shù)據(jù)集沒(méi)有建立索引,新記錄就插入到數(shù)據(jù)集的當(dāng)前位置(Insert)或末尾(Append)。6.7.3 刪除記錄調(diào)用Delete函數(shù)將刪除當(dāng)前記錄,并且使數(shù)據(jù)集回到dsBrowse狀態(tài)。如果窗體上有TDBNavigator構(gòu)件的話,用戶可以單擊導(dǎo)航器上的“Delete”按鈕刪除當(dāng)前記錄。當(dāng)前記錄被刪除后,下一條記錄就成為當(dāng)前記錄。如果刪除的本來(lái)就是最后一條記錄,則前一條記錄成為當(dāng)前記錄。6.7.4 修改整條記錄除了TDBGrid和TDBNavigator外,大部分?jǐn)?shù)據(jù)控件只能工作于數(shù)
42、據(jù)集的一個(gè)或幾個(gè)字段,而不是整條記錄。不過(guò),TDataSet提供了若干個(gè)方法可以直接修改整條記錄而不是單獨(dú)的字段,這些方法包括:.AppendRecord類似于Append,但可以給字段賦值,不需要調(diào)用Post;.InsertRecord類似于Insert,但可以給字段賦值,不需要調(diào)用Post;.SetFields對(duì)當(dāng)前記錄的字段賦值,需要顯式地調(diào)用Post。上述三個(gè)方法都要傳遞一個(gè)TVarRec類型的數(shù)組作為參數(shù),該數(shù)組的每一個(gè)元素對(duì)應(yīng)著一個(gè)字段的值。如果數(shù)組的元素個(gè)數(shù)小于數(shù)據(jù)集的字段個(gè)數(shù),剩下字段的值就是NULL。對(duì)于沒(méi)有建立索引的數(shù)據(jù)集來(lái)說(shuō),AppendRecord把一條新的記錄加到數(shù)據(jù)
43、集的末尾。對(duì)于已建立索引的數(shù)據(jù)集來(lái)說(shuō),新記錄將自動(dòng)移到一個(gè)恰當(dāng)?shù)奈恢谩etFields用于對(duì)當(dāng)前記錄的字段賦值。在調(diào)用SetFields之前,首先要調(diào)用Edit,使數(shù)據(jù)集進(jìn)入dsEdit狀態(tài)。調(diào)用了SetFields后,需要顯式地調(diào)用Post函數(shù)。調(diào)用SetFields時(shí),如果您只想對(duì)部分字段賦值,讓其他字段的值保持不變,可以用NULL或NIL去賦值。假設(shè)一個(gè)數(shù)據(jù)集中有五個(gè)字段,分別是Name、Capital、Continent、Area和Population,可以這樣對(duì)它們賦值:CountryTable.InsertRecord(Japan, Tokyo, Asia);上述程序在數(shù)據(jù)集中插
44、入了一條新的記錄,并且對(duì)前三個(gè)字段賦了值?,F(xiàn)在可以再次對(duì)當(dāng)前記錄賦值,不過(guò),這次只想對(duì)Area字段和Population字段賦值,程序就要這樣寫(xiě):With CountryTable DoBeginIf Locate(Name, Japan, loCaseInsensitive) thenBeginEdit;SetFields(NIL, NIL, NIL, 344567, 164700000);Post;End;End;注意:此處要用NIL而不是NULL,否則,前三個(gè)字段會(huì)被設(shè)為空。6.8 事 件TDataSet的事件主要分為兩大類,一類是Before系列,另一類是After系列,列表如下:.B
45、eforeOpen,AfterOpen發(fā)生在數(shù)據(jù)集打開(kāi)前后;.BeforeClose,AfterClose發(fā)生在數(shù)據(jù)集關(guān)閉前后;.BeforeInsert,AfterInsert發(fā)生在插入了一條新的記錄前后;.BeforeEdit,AfterEdit 發(fā)生在進(jìn)入dsEdit狀態(tài)前后;.BeforePost,AfterPost 發(fā)生在寫(xiě)數(shù)據(jù)集的前后;.BeforeCancel,AfterCancel發(fā)生在取消修改的前后;.BeforeDelete,AfterDelete發(fā)生在刪除記錄的前后。此外,當(dāng)數(shù)據(jù)集中增加了一條新的記錄時(shí)就會(huì)觸發(fā)OnNewRecord事件,當(dāng)“計(jì)算字段”的值需要重算時(shí)將觸發(fā)
46、OnCalcFields事件。Before系列的事件常常用來(lái)中止操作。例如,當(dāng)調(diào)用Delete函數(shù)試圖刪除當(dāng)前記錄時(shí),在當(dāng)前記錄將要?jiǎng)h除前會(huì)觸發(fā)BeforeDelete事件,可以在處理BeforeDelete事件的句柄中調(diào)用Abort或觸發(fā)一個(gè)異常放棄刪除當(dāng)前記錄,程序示例如下:Pocedure TForm1.TableBeforeDelete (Dataset: TDataset)BeginIf MessageDlg(Delete This Record?, mtConfirmation, mbYesNoCancel, 0) <> mrYes Then Abort;End;Aft
47、er系列的事件往往用來(lái)在狀態(tài)欄上通知用戶,程序示例如下:Procedure TForm1.Table1AfterDelete(DataSet: TDataSet);BeginStatusBar1.SimpleText := Format(有%d 條記錄,DataSet.RecordCount);End;OnCalcFields事件主要用于給出“計(jì)算字段”的值。AutoCalcFields屬性的值決定了什么時(shí)候會(huì)發(fā)生OnCalcFields事件。如果AutoCalcFields屬性設(shè)為T(mén)rue,下列情況下會(huì)發(fā)生OnCalcFields事件:.數(shù)據(jù)集被打開(kāi)時(shí);.在數(shù)據(jù)控件中,輸入焦點(diǎn)從一條記錄移到
48、另一條記錄;.在數(shù)據(jù)控件中,輸入焦點(diǎn)從一個(gè)字段移到另一個(gè)字段;.當(dāng)前記錄被修改或從數(shù)據(jù)庫(kù)中檢索了一條記錄。不過(guò),即使AutoCalcFields屬性設(shè)為False,當(dāng)數(shù)據(jù)集中的任意一個(gè)非計(jì)算字段的值發(fā)生變化時(shí)都會(huì)觸發(fā)OnCalcFields事件。由于OnCalcFields事件有可能是頻繁發(fā)生的,因此,處理OnCalcFields 事件的代碼要盡可能地簡(jiǎn)短。在AutoCalcFields屬性設(shè)為T(mén)rue的情況下,在處理OnCalcFields事件的句柄中不能修改數(shù)據(jù)集的數(shù)據(jù),因?yàn)橐坏┊?dāng)前記錄被修改,又要觸發(fā)OnCalcFields事件,從而導(dǎo)致無(wú)限循環(huán)。例如,假設(shè)您在處理OnCalcField
49、s事件的句柄中調(diào)用了Post,就會(huì)觸發(fā)OnCalcFields事件,導(dǎo)致再次調(diào)用Post,再次觸發(fā)OnCalcFields事件6.9 TBDEDataSetTBDEDataSet是從TDataSet繼承下來(lái)的,它提供了通過(guò)BDE(BorlandDatabase Engine)訪問(wèn)數(shù)據(jù)的能力。這一節(jié)主要介紹TBDEDataSet,讀者應(yīng)當(dāng)對(duì)前面介紹的TDataSet已經(jīng)有了比較深刻的認(rèn)識(shí)。與TDataSet一樣,TBDEDataSet也是虛擬的和抽象的,除非您想建立自定義的數(shù)據(jù)集,否則,一般不需要直接用到TBDEDataSet。TBDEDataSet重載了TDataSet中涉及記錄導(dǎo)航、索引和書(shū)簽的方法,增加了一些處理BLOB字
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年度出樣產(chǎn)品環(huán)保技術(shù)研發(fā)與應(yīng)用協(xié)議3篇
- 2024年食品級(jí)原材料安全運(yùn)輸與購(gòu)銷保障協(xié)議3篇
- 2024廣州二手房購(gòu)房合同
- FBM模式2024年度汽車(chē)租賃合同
- 2024年賽事組織與執(zhí)行合同
- 2024年簡(jiǎn)化版鋼管交易協(xié)議范例一
- 2025年生態(tài)環(huán)保型建筑施工安全生產(chǎn)責(zé)任書(shū)3篇
- 2024年財(cái)產(chǎn)抵押貸款合同
- 2024年飲料分銷合作伙伴協(xié)議3篇
- 2024智能交通系統(tǒng)技術(shù)開(kāi)發(fā)與實(shí)施合同
- 西那卡塞治療甲旁亢
- 無(wú)人駕駛 物流行業(yè)市場(chǎng)調(diào)研分析報(bào)告
- 電力工程施工人員培訓(xùn)方案
- 3-U9C操作培訓(xùn)-MRP基礎(chǔ)
- 8年級(jí)上冊(cè)(人教版)物理電子教材-初中8~9年級(jí)物理電子課本
- 2024至2030年中國(guó)銅制裝飾材料行業(yè)投資前景及策略咨詢研究報(bào)告
- 中金公司在線測(cè)評(píng)真題
- 項(xiàng)目資金管理統(tǒng)籌實(shí)施方案
- 2024供應(yīng)商大會(huì)策劃方案
- 政治-經(jīng)濟(jì)與社會(huì) 教材探究與分享參考答案高中政治統(tǒng)編版必修二
- 湖南省常德市桃源縣市級(jí)名校2024年中考數(shù)學(xué)模試卷含解析
評(píng)論
0/150
提交評(píng)論