Delphi提供Pack功能 |
|
jackkcg
站務副站長 發表:891 回覆:1050 積分:848 註冊:2002-03-23 發送簡訊給我 |
此為轉貼資料 Delphi提供Pack功能 Delphi目前已經是國內常見的資料庫編程工具,它在各方面表現不錯,在支援大型多層資料庫結構的同時也完全支援本地資料庫。對於本地資料庫中Delphi對FoxPro的支援也不錯,我曾經對VB、FoxPro、Delphi的資料庫操作速度進行比較,發現除了?動速度較慢外,其他各項Delphi均排在首位。而且Delphi幾乎支援所有原先FoxPro所擁有的功能,對於有一定編程經驗的人來說,Delphi成了編寫資料庫軟體的一把利器,因而Delphi迅速流行起來,Delphi在我國也佔有一席之地。 但是我在使用Delphi編程的過程中發現它也有不如人意的地方,特別是在本地資料庫dBase和Paradox方面,它居然不支援十分有用的Pack和Undelete功能。對於資料庫來說,因?是一個順序存儲文件,在刪除部分記錄時一般採用了軟刪除技術,也就是說將要刪除的記錄標記已刪除的標記,但並不立即從物理上刪除這些記錄(刪除後庫文件大小不變)。 這樣做可以避免僅僅刪除一條記錄就要將整個資料庫重新寫入記憶體,提高了讀寫的效率。但是如果資料庫長期不對已經被標記?刪除的記錄進行整理和真實刪除,資料庫就會越來越大,其中無用的資料所占的比率越來越大,使得資料庫的讀寫效率迅速下降,而且造成查詢速度的減慢。特別是在編寫人事管理資料庫應用軟體時,庫內要保存大量的圖形文件(人員的照片),而這些資料還時常需要添加和刪除,沒用的資料不能"Pack"將佔用巨大的硬碟空間,而且還將降低系統的運行速度。 這是編寫資料庫軟體的人必須考慮的一個問題。經過再三查找,我找到一些資料,解決了如何對資料庫進行pack,下面是其中的核心程式的一個例子,在看例子之前,我先做一些說明: 1. 對於dBase和Paradox庫,其Pack原理是不同的:如果是Paradox 表, 必須調用 DbiDoRestructure,重建資料庫結構;如果是 dBASE 表, 只需要調用DbiPackTable。 2. 在做Pack刪除時,必須以獨佔方式打開資料庫時。具體請參考一下的例子。 (?了節省篇幅,例子中只給出關鍵性的程式段) implementation uses BDE;//做PACK必須引用次單元裏的函數 {$R *.DFM} procedure TfrmPack.FormCreate(Sender: TObject); var DBName:String; begin DBName:=ExtractFilePath(Application.ExeName);//得到資料庫的位置 {設置Table} tblDBASE.DatabaseName:=DBName; tblParadox.DatabaseName:=DBName; tblDBASE.TableName:='dbsTest.dbf'; tblParadox.TableName:='pdxTest.db'; tblDBASE.Active:=True; tblParadox.Active:=True; end; {物理刪除資料庫記錄Pack a Paradox or dBASE table} // The table must be opened execlusively before calling this procedure... procedure TFrmPack.PackTable(FTable: TTable); var Props: CURProps; hDb: hDBIDb; TableDesc: CRTblDesc; begin FTable.Active := False; {當資料庫打開失敗時,這個迴圈語句能夠讓用戶重試} repeat try FTable.Exclusive := True; FTable.Active := True; {如果正常打開資料庫,則退出迴圈} Break; except on EDatabaseError do if Application.MessageBox( '以獨佔方式打開資料庫時,出現錯誤---重試否?', '資料庫錯誤', MB_OKCANCEL MB_DEFBUTTON1) < > IDOK then Exit; end; until False; try {Check()用於校正和報告DBI底層錯誤;DbiGetCursorProps()用於取表游標屬性} Check(DbiGetCursorProps(FTable.Handle, Props));// 獲得表的屬性已得到表的類型 {如果是Paradox 表, 必須調用 DbiDoRestructure,重建資料庫結構} if (Props.szTableType = szPARADOX) then begin FillChar(TableDesc, sizeof(TableDesc), 0); {從資料表游標獲取資料庫控制碼} Check(DbiGetObjFromObj(hDBIObj(FTable.Handle), objDATABASE, hDBIObj(hDb))); {設置表的描述結構的Name/Type/bPack屬性} StrPCopy(TableDesc.szTblName, FTable.TableName); StrPCopy(TableDesc.szTblType, Props.szTableType); TableDesc.bPack := True; {關閉表並調用api} FTable.Close; Application.ProcessMessages; Check(DbiDoRestructure(hDb, 1, @TableDesc, nil, nil, nil, False)); Application.ProcessMessages; FTable.Open; end { 如果是 dBASE 表, 只需要調用DbiPackTable...} else if (Props.szTableType = szDBASE) then begin Application.ProcessMessages; Check(DbiPackTable(FTable.DBHandle, FTable.Handle, nil, szDBASE, True)); Application.ProcessMessages; end {不是dBase和Paradox表} else raise EDatabaseError.Create('資料庫必須是 Paradox 或者 dBASE 類型,才能進行物理刪除操作!!'); finally FTable.Active := False; FTable.Exclusive := False; FTable.Active := True; end; end; procedure TfrmPack.BitBtndBaseClick(Sender: TObject); begin if OpenPictureDlg.Execute then DBImage1.Picture.LoadFromFile(OpenPictureDlg.FileName); end; procedure TfrmPack.BitBtnParadoxClick(Sender: TObject); begin if OpenPictureDlg.Execute then DBImage2.Picture.LoadFromFile(OpenPictureDlg.FileName); end; procedure TfrmPack.BitBtnPackdBASEClick(Sender: TObject); begin PackTable(tbldBASE);//物理刪除dDBSE庫 end; procedure TfrmPack.BitBtnPackParadoxClick(Sender: TObject); begin PackTable(tblParadox);//物理刪除Paradox庫 end; 本程式在Windows 2000 Professional下Delphi5.0 C/S版調試通過。調試時可裝入較大的Bmp圖片,先點"?"刪除記錄,然後查看資料庫的大小;再點"物理刪除"按鈕,再查看資料庫的大小,你會發現資料庫變小。本例子還可以進一步擴展,以增強其功能,限於篇幅,不必在此討論。有興趣的朋友可給我發Email: jollier@371.net,我可進一步解答有關的問題。
------
********************************************************** 哈哈&兵燹 最會的2大絕招 這個不會與那個也不會 哈哈哈 粉好 Delphi K.Top的K.Top分兩個字解釋Top代表尖端的意思,希望本討論區能提供Delphi的尖端新知 K.表Knowlege 知識,就是本站的標語:Open our mind |
P.D.
版主 發表:603 回覆:4038 積分:3874 註冊:2006-10-31 發送簡訊給我 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |