TTable中删除记录后,既然Delphi没有真正删除,有没有办法恢复?如何pack?(40分)

  • 主题发起人 主题发起人 houyg
  • 开始时间 开始时间
ttable.cancle
 
使用BDE函数 : "DBIPACKTABLE()", 具体用法参见BDE HELP.
 
说详细点:ttable.delete后,如果没有执行 ttable.post,那么,ttable.cancel可以放弃删除,即不删除;如果执行ttable.post,就真正删除了。
 
我的意思是说有多条记录删除之后,再恢复这些记录。
Table.Cancel好象只是取消对当前记录的修改。

我用DBIPackTable后,用Desktop打开,新增记录,
其记录序号仍然没有重新排过,这是否意味着没有Pack过?
 
详细用法:
设好TABLE1的属性, 包括TALBENAME, DATABASE NAME等。
特别注意的是TABLE1.EXCLUSIVE应为'TRUE'
这样才能对TABLE进行PACK TABLE.

DBIPACKTABLE(TABLE1.DBHANDLE,TABLE1.HANDLE,NIL,NIL,TRUE);

即可PACK TABLE.

另, 若在DELPHI IDE中, TABLE1的ACTIVE应为FALSE;
在FORM的ONCREATE中执行TABLE1.ACTIVE:=TRUE
来打开数据库, 否则在执行程序是会提示TABLE IS BUSY.
原因是在IDE中已经打开的TABLE, 无法的独占地打开TABLE.

 
DBIPackTable是整理数据库用的,不能恢复已删除的记录。

如果你因为操作时误删了记录而想恢复,建议把Table的CachedUpdates设为True,
对数据库操作完毕且确认无误后,调用ApplyUpdates和CommitUpdates提交数据。
如果不想提交,可以调用CancelUpdates恢复上次提交时的状态。
 
谢谢Liwei兄,我把Exclusive设为true,DBIPackTable就灵了。

那么,我能否恢复pack之前删除的记录呢?
 
(1) 如果你选用的是dbase,删除是可以恢复的,但是必须直接使用BDE函数
(2) 如果你选用的是Paradox或其他SQL DBMS,删除在以下条件下可以恢复:
a. 在一个Transcation被提交以前,可以使用Rollback操作恢复所有
对数据库的修改
b. 在数据表为CacheUpdate的情况下,可以在ApplyUpdates前使用
RevertRecord方法恢复被删除的指定记录,也可以CancelUpdates
恢复对数据库的修改。
除此以外,没有任何方法对数据库删除进行恢复
 
当你用用的是DBASE 恢复方法如下:

DbiUndeleteRecord(dBASETbl.Handle)。
 
我给你程序,你结合BDE HELP用。
在DELPHI 3 中为DBF数据库增加Undel,Pack等功能
在用Delphi 3 开发基于Dbf 数据库时,若用Ttable元件的Delete 方法删除
一条记录,同时CachedUpdates为True (或CachedUpdates为False,但调用了
ApplyUpdates方法),则Delphi 在该条记录的物理位置的首部用“*”打上
标记(正如用Foxpro或Dbase的Del命令一样)。
在Delphi 中对各种数据库(Paradox,Dbase 等)的底层操作均是通过数据库
引擎(BDE)进行的。对于Dbase数据库,缺省情况下,BDE将标有删除标记“
*”的记录过滤掉,不提供给上层应用程序,因此使用Delphi中Data Access
页上的元件或用DataBase DeskTop均无法对这些记录进行显示和操作,因而
无法象Foxpro 那样在必要时用Undel恢复删除或用Pack 进行彻底地物理删
除。日积月累,这类记录越来越多,占用了大量的磁盘空间,降低了操作时
间,降低了安全性。因此这就要求Delphi 能提供显示已被打有“*”标记的
记录的方法(DispDeleted ),能够恢复误删除方法(Undel ),以及物理
删除有“*”标记记录的方法(PackTable)。
既然有“*”标记的记录是在数据库引擎BDE中被过滤掉的,那么也只有通过
对BDE编程,使BDE 不过滤有“*”记录,从而使用Delphi中Data Access 页
上的元件或用DataBase DeskTop能对这些记录进行显示和操作。在Borland公
司提供的BDE API 接口数据结构中有一参数 curSOFTDELETEON,当它值为
True时,则BDE不过滤有“*”记录,当它为False时,则过滤。而BDE缺省时
curSOFTDELETEON为False。因此当我们需要显示和操作有“*”记录时,我们
可以通过编程将curSOFTDELETEON设为True,当我们不需要显示和操作有“*
”记录时,我们可以将curSOFTDELETEON设为False,值得注意的是,由于“*
”不是数据库的一个“Field",因此在允许显示有“*”记录时,Delphi并不
将“*”也也显示出来,这就让使用者难以区别该条记录是否是有“*”标记
。同样,BDE的API接口中也有一个变量bDeleteFlag,当bDeleteFlag为True
时,则此记录是有J“*”标记的,反之则没有。因此当需要时,我们可以对
BDE编程,取出该变量来进行判断。关于如何对BDE进行编程,请读者参考相
关资料,本文仅针对以上几个问题给出源程序和例子,以供读者参考。

// 判断Atable 中当前记录是否已被删除, 若返回值为True 则已被删除,
否则未被删除
Function GetDelFlag(Atable: Ttable):Boolean;
var
CP: CurProps;
RP: RecProps;
begin
with Atable do begin
UpdateCursorPos; // 同步 BDE 和 Delphi

Check(DbiGetCursorProps(Handle, CP));
// 确认是Dbase 表!且已置软删除
if CP.szTableType<>szDBASE then
raise EDatabaseError.Create('Not is DBASE DBF!');
if CP.bDeletedOn = False then
raise EDatabaseError.Create('Soft deletes is not on');

// 取出删除标记
Check(DbiGetRecord(Handle, dbiNOLOCK, nil, @RP));
GetDelFlag := RP.bDeleteFlag;
end;
end;

// 设置软删除标记.
// 若使SofeDelete=True 则使BDE 不过滤有“*”标记记录,否则,过滤
procedure SetSofDelete(Table: Ttable; SoftDelete: Boolean);
var
rslt: DBIResult;
Props: CURProps;
begin
Check(DbiGetCursorProps(Table.Handle, Props));
// 确认是Dbase 表
if StrIComp(Props.szTableType, szDBASE) <> 0 then
raise EDBEngineError.Create(DBIERR_NOTSUPPORTED);
// 确认能设置软删除
rslt := DbiValidateProp(hDBIObj(Table.Handle), curSOFTDELETEON,SoftDelete);
if rslt = DBIERR_NONE then
// 设置软删除
Check(DbiSetProp(hDBIObj(Table.Handle), curSOFTDELETEON, Longint(SoftDelete)))

else
raise EDBEngineError.Create(rslt);
end;

// 允许有“*”标记记录显示
procedure DispDeleted(Table: Ttable);
Begin
SetSofDelete(Table,True );
End;

// 不允许有“*”标记记录显示
procedure UndispDeleted(Table: Ttable);
Begin
SetSofDelete(Table,False );
End;

// 恢复删除
procedure Undel(dBASETbl: Ttable);
var
Cprops: CurProps;
begin
Check(DbiGetCursorProps(dBASETbl.Handle, Cprops));
// 确认是Dbase 表,且软删除已设置为True;
if StrIComp(Cprops.szTableType, szDBASE) <> 0 then
raise EDBEngineError.Create(DBIERR_NOTSUPPORTED);
if Cprops.bDeletedOn = False then
raise EDatabaseError.Create('Soft deletes is not on');
Check(DbiUndeleteRecord(dBASETbl.Handle));
end;


procedure TForm1.Button1Click(Sender: Tobject);
begin
Table1.Active:=True;
DispDeleted(Table1);
end;

procedure TForm1.Button3Click(Sender: Tobject);
begin
Undel(Table1);
end;

procedure TForm1.Button4Click(Sender: Tobject);
begin
GetDelFlag(Table1);
end;

end.
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
后退
顶部