В общем так. Возможность сжатия есть в dBase (там запись можно ещё и восстановить после удаления) и Paradox (можно только очистить пустые места). С остальными СУБД в этом плане не сталкивался. В зависимости от того, с чем ты работаешь, надо использовать разные функции. Для dBase я уже привёл, для парадокса - смотри код модуля. Это листинг из книжки Тейсейры и Пачеко "Дельфи 5". Чё будет непонятно - спрашивай, текст у меня есть.
| Цитата | unit DDGTbls;
interface
uses DB, DBTables, BDE;
type TdBaseTable = class(TTable) private FViewDeleted: Boolean; function GetIsDeleted: Boolean; function GetRecNum: Longint; procedure SetViewDeleted(Value: Boolean); protected function CreateHandle: HDBICur; override; public procedure Pack(RegenIndexes: Boolean); procedure UndeleteRecord; property IsDeleted: Boolean read GetIsDeleted; property RecNum: Longint read GetRecNum; property ViewDeleted: Boolean read FViewDeleted write SetViewDeleted; end;
TParadoxTable = class(TTable) private protected function CreateHandle: HDBICur; override; function GetRecNum: Longint; public procedure Pack; property RecNum: Longint read GetRecNum; end;
implementation
uses SysUtils;
{ TdBaseTable }
function TdBaseTable.GetIsDeleted: Boolean; { Returns a boolean indicating whether or not the current record } { has been soft deleted. } var RP: RECProps; begin if not FViewDeleted then // don't bother if they aren't viewing Result := False // deleted records else begin UpdateCursorPos; // update BDE from Delphi { Get current record properties } Check(dbiGetRecord(Handle, dbiNOLOCK, Nil, @RP)); Result := RP.bDeleteFlag; // return flag from properties end; end;
function TdBaseTable.GetRecNum: Longint; { Returns the physical record number of the current record. } var RP: RECProps; begin UpdateCursorPos; // update BDE from Delphi { Get current record properties } Check(dbiGetRecord(Handle, dbiNOLOCK, Nil, @RP)); Result := RP.iPhyRecNum; // return value from properties end;
function TdBaseTable.CreateHandle: HDBICur; { Overridden from ancestor in order to perform a check to } { ensure that this is a dBASE table. } var CP: CURProps; begin Result := inherited CreateHandle; // do inherited if Result <> Nil then begin { Get cursor properties, and raise exception if the } { table isn't using the dBASE driver. } Check(dbiGetCursorProps(Result, CP)); if not (CP.szTableType = szdBASE) then raise EDatabaseError.Create('Not a dBASE table'); end; end;
procedure TdBaseTable.Pack(RegenIndexes: Boolean); { Packs the table in order to removed soft deleted records } { from the file. } const SPackError = 'Table must be active and opened exclusively'; begin { Table must be active and opened exclusively } if not (Active and Exclusive) then raise EDatabaseError.Create(SPackError); try { Pack the table } Check(dbiPackTable(DBHandle, Handle, Nil, Nil, RegenIndexes)); finally { update Delphi from BDE } CursorPosChanged; Refresh; end; end;
procedure TdBaseTable.SetViewDeleted(Value: Boolean); { Allows the user to toggle between viewing and not viewing } { deleted records. } begin { Table must be active } if Active and (FViewDeleted <> Value) then begin DisableControls; // avoid flicker try { Magic BDE call to toggle view of soft deleted records } Check(dbiSetProp(hdbiObj(Handle), curSOFTDELETEON, Longint(Value))); finally Refresh; // update Delphi EnableControls; // flicker avoidance complete end; FViewDeleted := Value end; end;
procedure TdBaseTable.UndeleteRecord; begin if not IsDeleted then raise EDatabaseError.Create('Record is not deleted'); Check(dbiUndeleteRecord(Handle)); Refresh; end;
function TParadoxTable.CreateHandle: HDBICur; { Overridden from ancestor in order to perform a check to } { ensure that this is a Paradox table. } var CP: CURProps; begin Result := inherited CreateHandle; // do inherited if Result <> Nil then begin { Get cursor properties, and raise exception if the } { table isn't using the Paradox driver. } Check(dbiGetCursorProps(Result, CP)); if not (CP.szTableType = szPARADOX) then raise EDatabaseError.Create('Not a Paradox table'); end; end;
function TParadoxTable.GetRecNum: Longint; { Returns the sequence number of the current record. } begin UpdateCursorPos; // update BDE from Delphi { Get sequence number of current record into Result } Check(dbiGetSeqNo(Handle, Result)); end;
procedure TParadoxTable.Pack; var TblDesc: CRTblDesc; TempDBHandle: HDBIDb; WasActive: Boolean; begin { Initialize TblDesc record } FillChar(TblDesc, SizeOf(TblDesc), 0); // fill with 0s with TblDesc do begin StrPCopy(szTblName, TableName); // set table name szTblType := szPARADOX; // set table type bPack := True; // set pack flag end; { Store table active state. Must close table to pack. } WasActive := Active; if WasActive then Close; try { Create a temporary database. Must be read-write/exclusive } Check(dbiOpenDatabase(PChar(DatabaseName), Nil, dbiREADWRITE, dbiOpenExcl, Nil, 0, Nil, Nil, TempDBHandle)); try { Pack the table } Check(dbiDoRestructure(TempDBHandle, 1, @TblDesc, Nil, Nil, Nil, False)); finally { Close the temporary database } dbiCloseDatabase(TempDBHandle); end; finally { Reset table active state } Active := WasActive; end; end;
end. | |