利用GotoNearest方法執行不精確查找 窗體中的“不精確查找”按鈕的事件處理過程代碼如下:
procedure TForm1.Button1Click(Sender: TObject);
begin
with table1 do
begin
IndexFieldNames:='Company';
setkey;
FieldByName('Company').AsString:=Edit1.text;
GotoNearest;
label3.caption:=FieldByName('Company').AsString;
end;
end;
讀者可以利用 FindNearest 方法執行上面的不精確查找, 具體使用方法可以參看Findkey方法的使用。
在上面的例子中要設置table1的IndexFieldNames屬性為Company。
GotoNearest方法進行不精確查找
14.6 修改數據庫中的記錄
我們掌握了字段對象的概念和如何查找數據庫中的記錄之后,下面我便可以很方便地修改數據庫中現存的記錄了,一般來說,在程序中修改數據庫中的記錄包括下面這些步驟:
1、在數據庫中找到要修改的記錄,并將記錄指針移至該記錄。
2、調用Edit方法將與數據庫表相連的TTable部件設置成編輯狀態。
3、修改一個或多個字段。
4、調用post方法將修改后的記錄寫入數據庫。
以上這幾個步驟只是概述性的,具體實現時還有很多細節需要留心,我們通過一個例子來演示上面的全過程,以便讓讀者進一步地了解和掌握修改記錄的方法。
例14.6 我們為四個按鈕分別編寫了事件處理過程,用來遍歷數據庫中的記錄并對每個客戶記錄的Company字段進行修改,在程序對記錄進行更新操作時窗口中的控件都是無效的,在這個例子中我們還編寫了一個簡單的異常代碼塊用來確保在更新過程中出現異常時使控件恢復正常操作。
修改數據庫記錄
14.6.1 Edit方法Post方法
為了能讓用戶通過程序修改數據庫表中的記錄,TTable部件必須要處在編輯狀態下。在大多數情況下,數據庫表都是以瀏覽(只讀方式)方式打開的,也就是說它的每一個字段可以被讀取介不能被編輯修改。調用Edit 方法能夠將 TTable 部件置成編輯狀態, 當TTable部件處于編輯狀態后,我們才可以通過程序修改當前記錄指針所指向的記錄,但這樣修改后的記錄不會立即被寫入到磁盤上的實際數據庫表中。要想保存對記錄的修改,必須要調用Post方法,Post方法才真正將我們對記錄的修改寫入實際的數據庫表中。
一般來說,用來掃描整個數據庫表并修改每個記錄的某一個字段的程序如下所示:
with Table Do
begin
DisableControls;{在修改記錄的過程中,使其它部件無效}
First; {將記錄指針指向第一條記錄}
while not EOF do
begin
<讀取記錄的一個字段值到一個變量中>
<做適當的修改>
Edit; {將TTable部件置成編輯狀態}
<將修改后的字段值寫回到其對應的字段>
post; {將修改后的記錄寫回數據庫}
next; {修改下一條記錄}
end;
enablecontrols; {恢復其它部件的功能}
end;
程序都是對TTable部件進行操作,因此使用With語句來防止錯誤的擴散是很有意義的。在這里要注意Disablecontrols方法和EnableControls方法的使用。DisableControls方法是在程序修改TTable部件中的記錄時,切斷TTable部件與數據訪問部件TDatasource 部件的聯系。否則,在對TTable中的每一修改之后,TDataSource 部件都會更新窗體中所有數據瀏覽部件的顯示內容,這樣會急劇減慢處理過程而且浪費時間。EnableControls方法是與DisableControle方法執行相反的操作,它是用來恢復TTable部件與TDatasource部件的聯系并促使所有的數據瀏覽部件更新顯示。
調用First方法是將記錄指針移到數據庫表中的第一條記錄,確保程序從表中的第一條記錄開始進行修改。調用Next方法是將記錄指針從當前的記錄移到下一條記錄,這樣保證了從表中的第一條記錄開始逐條記錄進行修改,直到修改完最后一條記錄。如果不調用Next方法,程序將會陷入無窮的死循環。
14.6.2 實現異常保護的TRY...FINALLY語句
上面的程序存在著潛在的危險,在實際應用過程中,可能因為某些原因使得對數據庫表的更新不能進行下去。如當程序試圖執行Post方法將修改后的記錄寫回磁盤時,而又因為某種原因磁盤沒有準備好,這時便出現了異常。當出現異常時,應用程序會暫停下來并且會彈出一對話框顯示有關的錯誤信息,在用戶單擊錯誤信息對話框之后,程序將繼續執行到某一個地方去,而這個地方常常不是用戶所能預料到的。在我們的程序中, 在執行Post方法之前,窗體中所有的部件與TTable部件都已失去聯系。因此,這種異常將導致窗體中顯示的數據和數據庫無關。
Object Pascal中的Try...Finally語句為我們解決上述異常問題提供了一個解決方法。在Delphi中仍然采用了這一語句用來處理異常問題。實際上,Try...Finally 語句是把兩組語句組合在一起。語句的Try部分包含了可能產生異常的程序代碼,Finally部分包含了即使發生了異常也必須執行的一條或多條語句。在本例中, Finally 部分只包含了EnableControls方法調用這一條語句,我們將前面的代碼改寫并組合進Try...Finally 語句:
with Table Do
begin
DisableControls;{在修改記錄的過程中,使其它部件無效}
Try;
First; {將記錄指針指向第一條記錄}
while not EOF do
begin
<讀取記錄的一個字段值到一個變量中>
<做適當的修改>
Edit; {將TTable部件置成編輯狀態}
<將修改后的字段值寫回到其對應的字段>
post; {將修改后的記錄寫回數據庫}
next; {修改下一條記錄}
end;
enablecontrols;
Finally;{出現異常時,執行下面的程序}
enablecontrols; {恢復其它部件的功能}
end; {結束Try...Finally語句}
end;
在保留字Try和Finally之間的代碼跟前面的代碼是一樣的,它們用于在記錄之間移動記錄指針并處理對記錄的修改,這一段代碼可能會出現異常,當異常發生時,我們想保證執行EnableControls,以便窗體中各控件恢復與 TTable 部件的聯系, 因此我們必須將EnableControls語句放在Finally和結束語句End之間。
在這里要特別注意,請讀者們不要混淆了Try...Finally語句和Try...Except 語句。如果真正想在發生異常時采取相應的處理,就要使用Try...Except語句。Try... Finally語句只是用來處理當異常出現時,使應用程序執行Finally部分的語句,使程序繼續執行下去。Try...Except語句是實現異常處理,Try...Finally語句是實現異常保護。
有了上述這些概念,我們便可以提供這個例子的一些程序代碼,它涉及了所有這些內容。
程序清單:修改數據庫中的記錄
unit Unit26;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Grids, DBGrids, ExtCtrls, DB, DBTables, Buttons;
type
TForm1 = class(TForm)
DataSource1: TDataSource;
customerTable: TTable;
Panel1: TPanel;
DBGrid1: TDBGrid;
Panel2: TPanel;
UpperCaseFirstAddBtn: TButton;
UpperCaseSecondAddBtn: TButton;
MixedCaseFirstAddBtn: TButton;
MixedCaseSecondAddBtn: TButton;
BitBtn1: TBitBtn;
procedure ForceCase(TargetField:String;ToUpper:Boolean);
procedure UpperCaseFirstAddBtnClick(Sender: TObject);
procedure MixedCaseFirstAddBtnClick(Sender: TObject);
procedure UpperCaseSecondAddBtnClick(Sender: TObject);
procedure MixedCaseSecondAddBtnClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
const
upper=true;
Mixed=False;
{$R *.DFM}
Function IsUpper(ch:char):Boolean;
begin
If (ch>='A')and(ch<='z')then>='z')then>
IsUpper:=true
else
IsUpper:=False;
end;
procedure TForm1.ForceCase(TargetField:String;ToUpper:Boolean);
var
WorkBuffer:string;
i:Integer;
begin
with customerTable do
begin
DisableControls;
TRY
First; {將記錄指針移到第一條記錄處 }
While not EOF do
begin
WorkBuffer:=FieldByName(TargetField).AsString;
If ToUpper then
for i:=1 to Length(WorkBuffer)do
WorkBuffer[i]:=UpCase(WorkBuffer[i])
else
begin
for i:=1 to Length(WorkBuffer) do
If IsUpper(WorkBuffer[i]) then
WorkBuffer[i]:=chr(ord(WorkBuffer[i])+32);
WorkBuffer[1]:=UpCase(WorkBuffer[1])
end;
Edit;
FieldByName(TargetField).AsString:=WorkBuffer;
post;
Next;
end;
Finally
enableControls;
end;
end;
end;
procedure TForm1.UpperCaseFirstAddBtnClick(Sender: TObject);
begin
ForceCase('Addr1',Upper);
end;
procedure TForm1.MixedCaseFirstAddBtnClick(Sender: TObject);
begin
ForceCase('Addr1',Mixed);
end;
procedure TForm1.UpperCaseSecondAddBtnClick(Sender: TObject);
begin
ForceCase('Addr2',Upper);
end;
procedure TForm1.MixedCaseSecondAddBtnClick(Sender: TObject);
begin
ForceCase('Addr2',Mixed);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
customerTable.open;
end;
end. [1] [2] 下一頁 將修改后的字段值寫回到其對應的字段>做適當的修改>讀取記錄的一個字段值到一個變量中>將修改后的字段值寫回到其對應的字段>做適當的修改>讀取記錄的一個字段值到一個變量中>
|