天天看點

多層資料庫開發七:字 段 對 象

                                               第七章 字 段 對 象

  Delphi 4用TField來操縱資料集中的字段。不過,具體的字段實際上都是TField的派生類,是以,應用程式很少需要直接用到TField。

  當打開一個資料集的時候,Delphi 4會自動生成動态的、與資料類型有關的字段對象。當然,可以用字段編輯器建立永久的字段對象來代替動态的字段對象。

<b>7.1 具體的字段對象</b>

  Delphi 4支援24種類型的字段,它們都是從TField繼承下來的,包括:

.TADTFieldOracle8的ADT字段。ADT是Abstract Data Type的縮寫;

.TAggregateFieldTClientDataSet中自動維護的總計字段;

.TArrayField數組字段;

.TAutoIncFieldParadox表中的自動增長字段,取值範圍從-2,147,483,648到2,147,483,647;

.TBCDFieldBCD字段;

.TBooleanField布爾字段;

.TBlobField二進制資料,理論長度2GB;

.TBytesField二進制資料,理論長度2GB;

.TCurrencyField實數字段,取值範圍從5.0E-324到1.7E308;

.TDataSetField代表嵌套表的字段;

.TDateField日期字段;

.TDateTimeField日期和時間字段;

.TFloatField浮點字段,取值範圍從5.0 * 10E-324到1.7 * 10E308;

.TBytesField二進制資料,最大位元組數255;

.TIntegerField整型字段,取值範圍從-2,147,483,648到2,147,483,647;

.TLargeintField長整型字段,取值範圍從-263到263;

.TMemoField備注字段,理論長度2GB;

.TNumericField實數,取值範圍從3.4 E-4932到1.1E4932;

.TReferenceField一個引用其他資料集的指針;

.TSmallintField整型字段,取值範圍從-32,768到32,768;

.TStringField字元串字段,最大位元組數8192,包括NULL字元;

.TTimeField時間字段;

.TVarBytesField二進制資料,最大位元組數255;

.TWordField無符号整數,取值範圍從0到65,535。

<b>7.2 了解字段對象</b>

  就像Delphi 4的資料通路構件如TTable、TQuery一樣,TField也是非可視的,甚至在設計期都不能直接看到它,隻能通過資料通路構件和資料控件間接地通路它。

  Delphi 4建立的字段對象與字段的資料類型有關,例如,對于字元串類型的字段,建立的是TStringField對象。對于浮點類型的字段,建立的是TFloatField對象。下面我們就以TFloatField為例,看看怎樣操縱字段的顯示屬性:

.Alignment用于指定資料的對齊方式,如左對齊、居中、右對齊等;

.DisplayWidth用于指定資料的顯示寬度(以字元數為機關);

.DisplayFormat用于指定資料的顯示格式,如小數點的位置;

.EditFormat指定在編輯資料時顯示資料的格式。

  對于不同類型的字段對象來說,它們的屬性大部分是相同的,但也有一些屬性是專用的,例如,TFloatField的Precision屬性就是其他字段對象所沒有的。字段對象的大部分屬性隻是影響資料在窗體上的顯示屬性,但也有些屬性如Precision還影響使用者輸入和修改資料的格式。

  在一個打開的資料集中,所有的字段對象要麼都是動态的字段對象,要麼都是永久的字段對象。下面将詳細介紹這兩種不同類型的字段對象。

<b>7.3 動态字段對象</b>

  預設情況下,當把一個資料集放到資料子產品上并且打開它時,Delphi 4就會為資料集中的每一個字段自動生成一個動态的字段對象。之是以說它是動态的,一方面是因為它是自動生成的,另一方面是因為它總是反映實體資料集的情況,對于不同類型的字段來說,生成的字段對象的類型也不同。如果資料集的結構或其他資訊發生變化,當應用程式重新打開這個資料集時,就會基于最新的結構和資訊重建所有的字段對象。

  動态字段對象的生存期是臨時的,當資料集關閉時,這些字段對象也跟着消失。

  由此可見,動态字段對象的最大特點就是适應性強。利用這個特點,可以編寫一些通用的資料庫應用程式,它可以打開不同的資料集。要在應用程式中使用動态字段對象,您首先要把一個資料集構件放到窗體或資料子產品上,再把一個TDataSource構件放到窗體或資料子產品上,設定它的DataSet屬性指定資料集構件。把一個資料控件放到窗體上,設定它的DataSource屬性指定TDataSource 構件,有必要的話,還要指定要顯示哪個字段。最後,把資料集構件的Active屬性設為True,打開資料集,此時,就會自動建立動态字段對象。

  動态字段對象的不足之處是,要改變字段的顯示屬性、資料格式,需編寫代碼。即使您願意寫代碼,無論如何也無法改變字段的顯示順序,不能把某些字段暫時隐去,也不能增加新的字段如“計算字段”、“Lookup字段”。而且,也不能改變字段的資料類型。是以,很多情況下,應用程式往往要用永久字段對象來代替動态字段對象。

<b>7.4 永久字段對象</b>

  用永久字段對象代替動态字段對象的最大好處是,可以在設計期設定它的屬性。此外,永久字段對象還具有以下優勢:

.可以選擇部分字段;

.可以增加新的字段,包括“計算字段”和“Lookup字段”;

.可以改變原有字段的資料類型。

<b>7.4.1 怎樣建立永久字段對象</b>

  要建立永久字段對象,就要用到字段編輯器。用永久字段對象能夠保證應用程式每次運作時,使用者看到的總是這幾個字段,即使資料集的結構已發生改變。這樣,不管是資料控件還是程式代碼都不必擔心因為資料集的結構發生變化而導緻資料控件和程式代碼不能适應。不過,如果一個永久字段對象基于的源字段被删除,就會觸發異常。

  建立永久字段對象的一般步驟是:

  第一步是把一個資料集構件如TTable放到資料子產品上,設定DatabaseName屬性指定要通路的資料庫,設定TableName屬性指定要通路的表。

  第二步是輕按兩下TTable構件,Delphi 4将打開字段編輯器,如圖7.1所示。

  圖7.1 字段編輯器

  字段編輯器由标題欄、導航按鈕和一個可複選的字段清單組成。

  标題欄顯示資料集的名稱包括資料集所在的窗體或資料子產品的名稱,例如,假設資料集叫Customers,放在資料子產品CustomerData上,标題欄就顯示CustomerData.Customers。

  四個導航按鈕用于浏覽資料集的記錄,它們能夠向前翻一個記錄、向後翻一個記錄、翻到第一個記錄以及翻到最後一個記錄。如果資料集的Active屬性設為False或者資料集是空的,這四個導航按鈕将變灰。

  導航按鈕下面是一個可複選的清單框,列出了所有的永久字段。剛開始打開字段編輯器的時候,清單是空的,因為預設情況下,Delphi 4生成的是動态字段對象。

  第三步是單擊滑鼠右鍵,在彈出的菜單中選擇“Add Fields”指令,彈出“AddFields”對話框,如圖7.2所示。

  圖7.2 選擇字段

  選擇一個或幾個字段,然後單擊OK按鈕。Delphi 4将根據您選擇的字段建立永久字段對象,這些永久字段對象的名稱将出現在字段編輯器中,如圖7.3所示。

  圖7.3 列出永久字段對象的名稱

  導航按鈕都是灰的,可能是因為資料集沒打開。隻要建立了一個永久字段對象,以後每次打開資料集時,Delphi 4就不會建立動态字段對象。對于同一個資料集來說,動态字段對象和永久字段對象不可能同時存在。

  每次打開資料集時,Delphi 4都會在資料集中檢查每個永久字段對象所基于的字段是否還存在,如果字段已不存在,Delphi 4将觸發異常,并且拒絕打開資料集。

  一旦生成了永久字段對象,就可以把它看作是一個構件,在對象觀察器中設定它的屬性,建立事件句柄。事實上,一個永久字段對象就是一個構件。

  對于那些資料控件來說,隻要建立了一個永久字段對象,就隻有建立了永久字段對象的字段才能被資料控件顯示。

  建立了永久字段對象後,可以在單元檔案中找到該字段對象的聲明,示例如下:

TypeTForm1 = Class(TForm)

Table1: TTable;

Button1: TButton;

Table1XXH1: TStringField;

Table1XXH2: TBytesField;

Procedure Button1Click(Sender: TObject);

Private{ Private declarations }

Public{ Public declarations }

End;

<b>7.4.2 調整永久字段的順序</b>

  永久字段對象在字段編輯器中的排列順序就是這些字段在資料庫栅格(TDBGrid)中的顯示順序。是以,要改變字段的顯示順序,可以在字段編輯器中改變永久字段對象的排列順序,調整的辦法是:先選擇一個字段,然後用滑鼠把它拖到另一個位置,也可以按Ctrl+Up鍵把字段的順序上移,按Ctrl+Dn鍵把字段的順序下移。

  如果選擇了多個字段,而且這些字段本來并不是連續的,把它們拖到一個新位置後,這些本來不連續的字段現在也變成連續的了。

<b>7.4.3 增加新的字段</b>

  使用永久字段對象的另一個好處是,可以增加新的字段或者替換原有的字段。Delphi 4允許增加五種類型的字段:

.Data用于替換原有的字段,例如,改變字段的資料類型;

.Calculated增加一個“計算字段”,該字段的值由OnCalcFields事件給出;

.InternalCalc類似于“計算字段”,用于多層體系結構的客戶程式中;

.Lookup增加一個“Lookup”字段;

.Aggregate增加一個“總計字段”。

  上述五種類型的字段僅僅用于顯示,它們的資料隻在運作期有意義,不會影響原來的資料集。

  要增加一個新的字段,在字段編輯器上單擊滑鼠右鍵,在彈出的菜單中選擇“New Field”指令,彈出“New Field”對話框,如圖7.4所示

  圖7.4 建立新字段對話框

  “New Field”對話框由三部分組成:“Field Properties”分組框、“FieldType”分組框和“Lookup Definition”分組框。

  “Field Type”分組框中有三個單選按鈕,用于指定新建立的字段的生成類型(不是資料類型),預設的類型是“Data”,如果選擇“Lookup”,下面的“LookupDefinition”分組框就被激活。此外,也可以選擇“Calculated”表示要增加一個“計算字段”。

  如果資料集是TClientDataSet,“Field Type”框中就多了兩個單選按鈕,一個是“InternalCalc”,另一個是“Aggregate”。

  “Field Properties”分組框用于設定字段的屬性,其中,“Name”框用于輸入字段的名稱,Delphi 4會根據輸入的名稱字段在“Component”框中生成字段對象的名稱。“Type”框用于選擇字段的資料類型,Delphi 4支援生成ADT類型的字段。“Size”框用于輸入字段的長度,對于String、Bytes和VarBytes類型的字段必須輸入長度,其他類型的字段則不必。

<b>7.4.4 增加“Data”類型的字段</b>

  增加一個“Data”類型的字段主要是為了替換原有的某個字段,尤其是替換字段的資料類型。例如,假設一個字段的類型本來是TSmallIntField,現在想把它改成TIntegerField,由于通過程式設計是無法改變一個字段的資料類型的,隻能先把這個字段删掉,再增加一個“Data”類型的字段,把它的資料類型設為Integer。

  增加一個“Data”類型的字段的一般步驟是:

  第一步是在字段編輯器中删除要被替代的永久字段,記住它的名稱。

  第二步是單擊滑鼠右鍵,在彈出的菜單中選擇“New Field”指令,彈出“NewField”對話框。在“Name”框輸入字段的名稱,必須與要替換的字段的名稱完全相同,這樣才能從原來這個字段擷取資料。

  第三步是設定新字段的資料類型和長度,必須與原來的資料類型不同。對于String類型的字段來說,僅僅改變字段長度是不夠的。要注意的是,資料類型既要有所差別,新的資料類型還必須與原有的資料相容。

  第四步是在“Field Type”分組框内選擇“Data”,然後單擊OK按鈕。至此,就建立了一個新的字段,該字段将代替原有的某個字段。

<b>7.4.5 增加“Calculated”類型的字段</b>

  “計算字段”值是在處理OnCalcFields事件的句柄中給出的。增加一個“Calculated”類型的字段的一般步驟是(前面幾個公共的步驟省略):

  第一步是在“Name”框内輸入字段的名稱,不能與已有字段的名稱相同。

  第二步是在“Type”框内選擇字段的資料類型,在“Size”框内指定資料長度,如果字段的類型是TStringField、TBytesField或TVarBytesField的話。

  第三步是在“Field Type”分組框内選擇“Calculated”,然後單擊OK按鈕。

  第四步是在窗體或資料子產品上單擊資料集構件,然後建立處理OnCalcFields事件的句柄,在句柄中給出“計算字段”的值,程式示例如下:

  CityStateZip.Value := City.Value + ', ' + State.Value + ' ' + Zip.Value;

  如果沒有建立處理OnCalcFields事件的句柄,或者在句柄中沒有給出“計算字段”的值,“計算字段”的值就是空的。

  要說明的是,如果資料集是TClientDataSet或TQuery,還可以增加一個“InternalCalc”類型的字段。“InternalCalc”類型的字段與“Calculated”類型的字段非常相似,不同的是,對于TClientDataSet來說,“InternalCalc”類型的字段的值随其他字段的值一起被存取。

<b>7.4.6 增加“Lookup”類型的字段</b>

  所謂“Lookup”類型的字段,就是它的值能且隻能從另一個資料集中擷取。

  增加一個“Lookup”類型的字段的一般步驟是(前面幾個公共的步驟省略):

  第三步是在“Field Type”分組框内選擇“Lookup”,此時将激活下面的“LookupDefinition”分組框。

  第四步是在“Lookup Definition”分組框的“Dataset”框内選擇一個資料集,這個資料集不能是“計算字段”所在的資料集,否則會觸發異常。

  第五步是在“Lookup Definition”分組框的“Key Fields”框内選擇一個字段作為關鍵字段,如果要用幾個字段作為關鍵字段,您可以直接在“Key Fields”框内輸入這些字段的名稱,彼此之間用分号隔開。作為關鍵字段的字段必須都建立了永久字段對象。

  第六步是在“Lookup Definition”分組框的“Lookup Keys”框内選擇一個字段作為關鍵字段,用來與第五步選擇的字段比對。注意:這裡列出的是“Dataset”框内指定的資料集中的字段。如果要用幾個字段作為關鍵字段,您可以直接在“Lookup Keys”框内輸入這些字段的名稱,彼此之間用分号隔開。

  第七步是在“Lookup Definition”分組框的“Result Field”框内選擇一個字段,該字段的值将傳回給新增加的“Lookup”類型的字段。

  如果既定義了“計算字段”,又定義了“Lookup”類型的字段,“Lookup”類型的字段的值将先确定,這樣,在處理OnCalcFields事件的句柄中,可以引用“Lookup”類型的字段的值。

  TField有一個LookupCache屬性,對于“Lookup”類型的字段來說,如果把這個屬性設為True,當第一次打開資料集時,把“Lookup”類型的字段的值放到緩存中,以後就可以直接從緩存中讀取該字段的值,而不必從另一個資料集中去檢索。顯然,這可以提高應用程式的性能,尤其是當另一個資料集位于遠端伺服器上的時候。

  不過,如果“KeyFields”框内指定的字段太多,最好把LookupCache屬性設為False。

  注意:如果是在運作期把LookupCache屬性設為True,應當調用RefreshLookupList以初始化緩存。

  這裡順便要介紹一個技巧,可以通過程式設計為“Lookup”類型的字段提供資料,這樣可以避開從另一個資料集中擷取資料。首先要建立一個TLookupList的對象執行個體,調用Add建立一組資料的清單。然後設定字段的LookupList屬性指定TLookupList的對象執行個體,并且把LookupCache屬性設為True。以後,“Lookup”類型的字段的值就從清單中讀取。

<b>7.4.7 增加“Aggregate”類型的字段</b>

  隻能在TClientDataSet建立的資料集中增加“Aggregate”類型的字段,其一般步驟如下:

  第二步是在“Type”框内選擇字段的資料類型,一般選“Aggregate”。

  第三步是在“Field Type”分組框内選擇“Aggregate”,然後單擊OK按鈕。

  第四步是在字段編輯器中單擊剛剛建立的“Aggregate”類型的字段,設定Expression屬性指定一個表達式。

<b>7.4.8 删除永久字段對象</b>

  要删除一個永久字段對象,首先要打開字段編輯器,然後選擇要删除的字段,按下Del鍵。也可以用滑鼠右鍵單擊要删除的字段,在彈出的菜單中選擇“Delete”指令。

  對于永久字段對象來說,一旦被删掉,應用程式就不再能通路它。如果以後又想恢複,您隻能重新建立一個新的永久字段對象,原先的屬性和事件句柄都丢失了。

  如果把所有的永久字段對象都删掉,下次打開資料集時,就會自動建立動态字段對象。

<b>7.5 設定永久字段對象的屬性</b>

  使用永久字段對象的一個優勢是可以在設計期設定它的屬性、建立事件句柄。例如,可以設定字段的顯示寬度、它的值是否能修改。

  要設定永久字段對象的屬性和建立事件句柄,首先要打開字段編輯器,在字段編輯器中選擇一個字段,然後在對象觀察器中進行有關操作。

<b>7.5.1 設定字段的顯示和編輯屬性</b>

  TField提供了若幹個屬性由于設定字段的顯示和編輯屬性,這些屬性如下所列:

.Alignment設定字段在資料控件中的對齊方式(左、居中、右);

.ConstraintErrorMessage當使用者的輸入違反糾錯規則時顯示由此屬性指定的資訊;

.CustomConstraint設定一個本地使用的糾錯規則;

.Currency設為True表示按貨币格式顯示;

.DisplayFormat設定字段在資料控件中的顯示格式;

.DisplayLabel設定字段在資料庫栅格中的列标簽;

.DisplayWidth設定字段在資料控件中的顯示寬度;

.EditFormat設定字段在編輯時的顯示格式;

.EditMask設定使用者編輯資料時必須遵守的規則;

.FieldKind指定字段的生成類型;

.FieldName指定字段的名稱;

.HasConstraints如果字段已經有糾錯規則,這個屬性就傳回True;

.ImportedConstraint傳回伺服器端或資料字典中的糾錯規則;

.Index指定字段在資料集中的序号;

.LookupDataSet指定另一個資料集,以從中查找字段的值;

.LookupKeyFields指定一個或幾個字段,用于與關鍵字段比對;

.LookupResultField指定一個字段,該字段的值将複制給Lookup字段;

.MaxValue指定字段的最大值;

.MinValue指定字段的最小值;

.Name指定永久字段對象的内部名稱如Table1XXH;

.Origin傳回字段在資料集中原先的名稱;

.Precision指定字段的有效位;

.ReadOnly設為True表示字段的值是隻讀的;

.Size指定字段的長度(以字元為機關);

.Tag給每個字段對象一個識别号;

.Transliterate設為True表示将根據驅動程式進行轉換;

.Visible設為False表示這個字段不出現在資料控件中。

  要說明的是,有些屬性并不适用于某些類型的字段,例如,對于一個TStringField類型的字段來說,它就沒有Currency、MaxValue、DisplayFormat等屬性,對于一個TFloatField類型的字段來說,它就沒有Size屬性。

  上述屬性也可以在運作期設定,例如,要設定Customers表的CityStateZip字段的ReadOnly屬性,程式這麼寫:

   CustomersCityStateZip.ReadOnly := True;

   注意:不能用字段的名稱來通路上述屬性,而要用字段對象的名稱來通路。

<b>7.5.2 設定使用者的輸入格式</b>

  EditMask屬性僅适用于TStringField、TDateField、TTimeField和TDateTimeField類型的字段,用于設定使用者的輸入格式。

  要設定EditMask屬性,可以在對象觀察器中單擊EditMask屬性邊上的省略号按鈕打開“Input Mask Editor”對話框,如圖7.5所示。

  圖7.5 設定EditMask屬性對話框

  既可以在“Sample Masks”框内選擇一種現成的格式,也可以自定義格式。單擊“Masks”按鈕可以選擇更多的格式。

<b>7.5.3 使用預設的顯示格式</b>

  對于TFloatField、TCurrencyField、TIntegerField、TSmallIntField、TWordField、TDateField、TDateTimeField和TTimeField類型的字段來說,Delphi 4提供了若幹個例程,能夠使這些字段按預設的格式顯示。這些例程都是在SysUtils單元中聲明的,包括:

.FormatFloat适合于TFloatField和TCurrencyField;

.FormatDateTime适合于TDateField、TTimeField和TDateTimeField;

.FormatCurr适合于TCurrencyField。

  所謂預設的格式,實際上是在“控制台”中設定的。可以打開“控制台”,輕按兩下“區域設定”的圖示,就會看到那兒設定了有關數字、貨币、時間和日期的格式。例如,如果區域是United States,對于TFloatField類型的字段來說,它的顯示格式就是$1234.56。

  當然,無論是在設計期還是在運作期,都可以重新設定DisplayFormat屬性和EditFormat屬性指定字段的顯示格式。也可以在處理OnGetText事件和OnSetText事件的句柄中自定義字段的顯示格式。

<b>7.5.4 處理事件</b>

  就像大多數構件一樣,永久字段對象也有事件,可以在設計期建立處理事件的句柄。下面列出了TField的事件:

.OnChange當字段的值改變的時候觸發這個事件;

.OnGetText當程式試圖檢索字段的值時将觸發這個事件;

.OnSetText當程式試圖設定字段的值時将觸發這個事件;

.OnValidate當字段的值将要寫到記錄緩沖區中時将觸發這個事件。

  其中,OnGetText事件和OnSetText事件用于設定字段的顯示格式,OnChange事件用于對資料的改變作出反應,例如禁止或允許某個菜單項。OnValidate事件對字段的值進行校驗。

<b>7.5.5 調用方法</b>

  下面用于列出了TField的方法:

.AssignValue用于對字段指派,它會自動進行類型轉換;

.Clear把字段的值清為NULL;

.GetData把未格式化的資料寫到一個緩沖區中;

.IsValidChar判斷某個字元對字段來說是否合法;

.SetData把緩沖區中未格式化的資料指派給字段;

.FocusControl把輸入焦點移到字段所在的資料控件上。如果窗體上有幾個資料控件顯示一個字段的值,FocusControl會把輸入焦點移到第一個顯示該字段的資料控件上。

<b>7.6 屬 性 集</b>

  如果多個字段的顯示屬性是相同的或大緻相同的,不必重複它們的屬性,可以設定一個字段的屬性如Alignment、DisplayWidth、DisplayFormat、MaxValue、MinValue,然後建立一個屬性集加到資料字典中。這樣,其他字段就可以從資料字段中引入屬性集。

  要建立一個屬性集,首先要打開字段編輯器,選擇一個永久字段,然後在對象觀察器中設定有關屬性。設定好後,在字段編輯器上單擊滑鼠右鍵,在彈出的菜單中選擇“Save Attributes”指令,彈出“Save Attributes As”對話框,如圖7.6所示。

  圖7.6 儲存屬性集

  預設情況下,屬性集的名稱是表名加字段名,例如CustomCompany,可以改變這個名稱。

  也可以在SQL Explorer中建立屬性集。在SQL Explorer中建立屬性集的好處是,您可以指定字段的類型,而且還可以指定一個資料控件如TDBEdit、TDBCheckBox等,當基于該屬性集的字段拖到窗體上時會自動把這個資料控件加到窗體上。

  建立了屬性集後,其他字段就可以引入這個屬性集。首先也要打開字段編輯器,選擇要引入屬性集的字段,單擊滑鼠右鍵,在彈出的菜單中選擇“Associate Attributes”指令,彈出“Associate Attributes”對話框,如圖7.7所示。

  圖7.7 引入屬性集

  選擇一個屬性集,單擊OK按鈕,該屬性集中的屬性将應用到剛才選擇的字段中,這就是所謂的引入屬性集。

  如果以後又不想使用該屬性集中的屬性,還得打開字段編輯器,選擇一個字段,然後單擊滑鼠右鍵,在彈出的菜單中選擇“Unassociate Attributes”。

<b>7.7 顯示、轉換和通路字段的值</b>

  資料控件能夠自動顯示字段的值,在允許編輯的情況下,使用者可以在資料控件中修改字段的值,并且把修改後的值寫回到資料集中,這一切都不需要寫代碼。

  應用程式可以通過TField的Value屬性通路字段的值,例如,下面這行代碼把CustomersCompany字段的值顯示在編輯框Edit1中:

  Edit1.Text := CustomersCompany.Value;

  從理論上講,Value屬性可以通路任何資料類型的字段的值。不過,很多資料控件隻能傳遞字元串類型的值,是以,需要對Value屬性進行轉換。

  幸運的是,TField中提供了衆多的轉換功能,可以按特定的資料類型來通路一個字段的值,例如,AsString可以把數字或布爾型的字段按字元串類型來通路。

  AsVariant适用于所有的資料類型。要說明的是,轉換并不總是成功的,例如,AsDateTime可以把一個字元串轉換為日期、時間,但該字元串本身必須能識别為日期時間格式,而不能是一個普通的字元串。有些情況下,雖然轉換可以進行,但有可能丢失精度。

  用Value屬性通路字段的值需要事先知道字段對象的名稱,而很多情況下,往往并不知道字段對象的名稱,但字段的名稱卻是知道的。是以,應用程式往往通過字段的序号或名稱來通路字段的值。

  資料集構件都有一個Fields屬性,這是一個數組,它的每一個元素代表一個字段,這樣就可以按序号來通路某個字段的值,序号是從0開始的。例如,下面的代碼把Customers表的第7個字段顯示到編輯框Edit1中:

  Edit1.Text := CustTable.Fields[6].AsString;

  下面的代碼把第7個字段的值設為編輯框Edit1中的内容:  

   Customers.Edit;

   Customers.Fields[6].AsString := Edit1.Text;

   Customers.Post;

   不過,按序号來通路字段的值不是很安全,因為如果記錯了序号,就得不到正确的結果。是以,我們推薦按字段名稱來通路字段的值,這就要用到FieldByName函數。

  要調用FieldByName函數,得把字段的名稱作為參數傳遞給FieldByName函數。例如,下面的代碼把Customers表的CustNo字段顯示到編輯框Edit2中:

   Edit2.Text := Customers.FieldByName('CustNo').AsString;

  下面的代碼把CustNo字段的值設為編輯框Edit2中的内容:

   Customers.FieldByName('CustNo').AsString := Edit2.Text;

   在多層體系結構的應用程式中,客戶程式向應用伺服器申請更新資料時有可能出錯,這時候可以用CurValue屬性檢查字段目前的值,因為字段的值是随時有可能修改的,尤其是在多使用者的環境下,是以,知道字段目前的值是很有必要的。

<b>7.8 字段級糾錯</b>

  所謂字段級糾錯,就是事先定義一些規則或條件,字段的值必須符合這些規則或條件,否則就認為出錯。字段對象可以借用SQL伺服器糾錯,也可以建立自定義的糾錯。

  大多數SQL伺服器都定義了糾錯功能,而客戶程式則可以借用伺服器糾錯。TField的ImportedConstraint屬性可以傳回伺服器的糾錯規則,實際上是一個字元串,其文法類似于SQL語句,例如:

  Value &gt; 0 and Value &lt; 100

  如果伺服器的糾錯仍然不能滿足要求的話,可以用CustomConstraint屬性自己定義糾錯規則。這個屬性與ImportedConstraint屬性不同的是,如果伺服器端的糾錯規則發生改變,ImportedConstraint屬性也将改變,而自定義的糾錯規則是不變的。

  自定義的糾錯隻适用于本應用程式,并且隻對使用者輸入的資料進行校驗,對發向應用伺服器或從應用伺服器接收到的資料無能為力。

  要自定義糾錯規則,就要用到CustomConstraint屬性指定糾錯規則,并且設定ConstraintErrorMessage屬性指定一個資訊,當字段的值違反糾錯規則時就會顯示這個資訊。自定義的糾錯規則類似于SQL語句的Where部分,例如:X &gt; 0 and X &lt; 100其中,X隻是一個符号,用來引用字段的值,符号本身是無關緊要的,隻要在糾錯表達式中保持一緻就行了。

<b>7.9 Oracle 8的對象字段</b>

  Delphi 4是發揮Oracle 8對象關聯功能的最佳工具,它支援四種最新的字段,包括ADT(抽象資料類型)、數組、資料集(嵌套表)、引用,它們所對應的字段類型如下所列:

.TADTField代表一個ADT字段;

.TArrayField代表一個數組字段;

.TDataSetField代表一個資料集字段;

.TReferenceField代表一個引用字段,指向另一個ADT字段。

  上述四種類型的字段統稱為對象字段,它們的一個基本特征是包含或引用了另一個字段。如果一個資料集包含對象字段,隻要在設計期建立了對象字段的永久字段對象,就會自動為這些對象字段所包含或引用的子字段建立永久字段對象。同時,資料集構件的ObjectView屬性自動設為True。在ObjectView屬性設為True的情況下,資料集中的字段按照它們的繼承關系以樹狀存儲,而不是按原先的序号線性存儲。

  下面列出了對象字段所特有的一些屬性和方法,用于操縱它所包含或引用的子字段:

.Fields用這個屬性可以通路對象字段包含或引用的子字段;

.ObjectType傳回對象的類型;

.FieldCount傳回對象字段所包含或引用的子字段個數;

.FieldValues用這個屬性可以通路對象字段包含或引用的子字段的值。

<b>7.9.1 ADT字段</b>

  ADT是一種使用者自定義的字段類型,有點類似于結構,它可以包含大多數類型的字段,包括數組、引用和嵌套表。

  要通路一個ADT類型的字段有幾種方式,最好先要建立永久字段對象。假設一個ADT類型的字段叫Address,它包含了四個子字段,分别是Street、City、State、Zip。如果為Address字段建立了永久字段對象的話,将看到下列永久字段對象:

CustomerAddress: TADTField;

CustomerAddrStreet: TStringField;

CustomerAddrCity: TStringField;

CustomerAddrState: TStringField;

CustomerAddrZip: TStringField;

  這樣,就可以把對象字段的子字段當作一個普通的字段使用,例如:

  CityEdit.Text := CustomerAddrCity.AsString;

  不過,上述代碼假設已經建立了對象字段的永久字段對象,如果沒有建立永久字段,就要用下面的方式來通路對象字段的子字段:

  CityEdit.Text := Customer.FieldByName('Address.City').AsString;

  可以用TADTField的FieldValues屬性通路子字段的值,例如:

  CityEdit.Text := TAdtField(Customer.FieldByName('Address'))[1];

  由于FieldValues屬性是TObjectField的預設屬性,是以,上述代碼可以改為:

  CityEdit.Text := TAdtField(Customer.FieldByName('Address')).FieldValues[1];

  上述代碼也可以改為用Fields屬性,例如:CityEdit.Text := TAdtField(Customer.FieldByName('Address').Fields[1].AsString;

  甚至還可以這樣寫:CityEdit.Text :=TADTField(Customer.FieldByName('Address').Fields.FieldByName('City').AsString; 

  由此可見,通過永久字段對象來通路對象字段的子字段是最簡便的。此外,通過資料集構件的FieldValues屬性也可以通路ADT字段,例如:

  Customer.Edit;Customer['Address.City'] := CityEdit.Text;Customer.Post;

  下面這行代碼把Address字段的City子字段的值顯示到編輯框CityEdit中:

  CityEdit.Text := Customer['Address.City'];

<b>7.9.2 數組字段</b>

  所謂數組字段,其概念類似于數組,它所包含的子字段的類型是相同的,而ADT字段所包含的子字段的類型可以是不同的。數組字段的子字段可以是普通的字段,也可以是ADT字段,但不能是另一個數組字段。

  要通路資料集中的數組字段有幾種方式,下面是一種典型的通路方式:

var

OrderDates: TArrayField;

I: Integer;

Begin

For I := 0 to OrderDates.Size - 1 Do

If OrderDates.Fields[I].Is Null then Break;

OrderDateListBox.Items.Add(OrderDates[I]);

  假設有一個數組字段叫TelNos_Array,它有6個字元串類型的子字段。當為TelNos_Array字段建立永久字段對象時,同時将建立6個子字段的永久字段對象:

CustomerTelNos_Array: TArrayField;

CustomerTelNos_Array0: TStringField;

CustomerTelNos_Array1: TStringField;

CustomerTelNos_Array2: TStringField;

CustomerTelNos_Array3: TStringField;

CustomerTelNos_Array4: TStringField;

CustomerTelNos_Array5: TStringField;

  下面這行代碼通路其中的第一個子字段:

   TelEdit.Text := CustomerTelNos_Array0.AsString;

  如果沒有為數組字段建立永久字段對象,隻能通過FieldValues屬性來通路子字段的值,但必須把資料集構件的ObjectView屬性設為True。例如:

  TelEdit.Text := TArrayField(Table1.FieldByName('TelNos_Array')).FieldValues[1];

  TelEdit.Text := TArrayField(Table1.FieldByName('TelNos_Array'))[1];

  上述代碼也可以這樣寫:TelEdit.Text := TArrayField(Customer.FieldByName('TelNos_Array').Fields[1].AsString;

<b>7.9.3 資料集字段</b>

  通過資料集字段,可以非常簡單地維護表格與表格之間的一對多關系。通過TDataSetField的NestedDataSet屬性可以通路資料集字段所嵌套的子資料集。

  為了支援資料集字段,Delphi 4的TDBGrid構件作了改寫,凡是顯示資料集字段的欄都有一個省略号按鈕,使用者單擊這個省略号将打開一個新的視窗,這個視窗也用一個TDBGrid構件顯示嵌套表的資料。當然,要打開這個視窗,也可以調用TDBGrid的ShowPopupEditor函數,例如:

  DBGrid1.ShowPopUpEditor(DbGrid1.Columns[7]);

  要通路嵌套表中的資料,最好要為資料集字段建立永久字段對象,然後用TNestedTable或TClientDataSet的DatasetField屬性指定這個字段。

<b>7.9.4 引用字段</b>

  引用字段所表達和存儲的是一個指針,指向另一個ADT對象,這個ADT對象通常是另一個資料集中的一條記錄。被引用的ADT對象中的資料可以像嵌套表一樣來通路,也可以通過TReferenceField的Fields屬性來通路。

  與資料集字段一樣,在TDBGrid構件中,凡是顯示引用字段的欄都有一個省略号按鈕,使用者單擊這個省略号按鈕将打開一個新的視窗,這個視窗也用栅格顯示被引用的ADT對象中的資料。要打開這個視窗,也可以調用TDBGrid的ShowPopupEditor函數,例如:

  DBGrid1.ShowPopUpEditor(DbGrid1.columns[7]);

  要通路被引用的ADT對象中的資料,首先要為引用字段建立永久字段對象,然後然後用TNestedTable或TClientDataSet的DatasetField屬性指定這個字段。

  假設一個引用字段對象叫CustomerRefCity,下面的代碼通路它所引用的ADT對象中的某個字段,兩行代碼的效果是一樣的。

  CityEdit.Text := CustomerRefCity.Fields[1].AsString;

  CityEdit.Text := CustomerRefCity.NestedDataSet.Fields[1].AsString;

  要對引用字段指派,需要用SQL SELECT語句,程式示例如下:

AddressQuery: TQuery;

CustomerAddressRef: TReferenceField;

Address.SQL.Text :='SELECT REF(A) FROM AddressTable A WHERE A.City = "San Francisco"';

AddressQuery.Open;CustomerAddressRef.Assign(AddressQuery.Fields[0]);

<b>7.9.5 顯示ADT字段和數組字段</b>

  ADT字段和數組字段具有一個共同的特點,它們都包含子字段。Delphi 4對一些資料控件作了改寫,像TDBEdit、TDBGrid都支援ADT字段和數組字段。

  對于那些具有DataField屬性的資料控件來說,它們顯示ADT字段和數組字段的值時,會自動用一個下拉清單顯示它們的子字段的值。

  TDBGrid怎樣顯示ADT字段和數組字段的值取決于資料集構件的ObjectView屬性怎樣設定。如果ObjectView屬性設為False,每個子字段集中顯示在一欄中。如果ObjectView屬性設為True,顯示ADT字段和數組字段的欄将出現一個下拉的箭頭,單擊此箭頭将使栅格擴充,顯示所有子字段的值。