Delphi 10.1中ADOQuery编辑DBF数据库出现更新行找不到错误求助
Delphi 10.1中ADOQuery编辑DBF记录Post报错问题
问题现象
在Delphi 10.1中使用ADOQuery的Edit和Post方法编辑DBF数据库记录时,调用ADOQuery.Post时出现错误:
指定用于更新的行未找到。自上次读取后部分值可能已更改
编辑操作在打开的第二个窗体中进行,通过属性传递TADOConnection、TDataSource和TADOQuery对象,需求是选中DBGrid中的单元格后点击编辑按钮修改其内容。
相关代码
公共属性定义
public { Public-Deklarationen } selectedRow, selectedCol : Integer; property ADOConnection : TADOConnection read FADOConnection write FADOConnection; property ADOQuery : TADOQuery read FADOQuery write FADOQuery; property DataSource : TDataSource read FDataSource Write FDataSource; end;
DBGrid单元格点击事件
procedure TForm3.DBGrid1CellClick(Column: TColumn); begin selectedCol := DBGrid1.SelectedField.Index; selectedRow := DBGrid1.DataSource.DataSet.RecNo; end;
编辑按钮点击事件
procedure TForm3.BtnEditClick(Sender: TObject); var iReplacement : string; begin iReplacement := InputBox('Wert', 'Ändere den Wert "' + DBGrid1.Columns[selectedCol].Field.FieldName + '" für: ' + ADOQuery.Fields[0].AsString + ', ' + ADOQuery.Fields[2].AsString, ADOQuery.Fields[selectedCol].AsString); try ADOQuery.Edit; ADOQuery[DBGrid1.Columns[selectedCol].Field.FieldName] := iReplacement; ADOQuery.Post; //ADOQuery.Refresh; except on E: Exception do MessageDlg('Error: ' + E.Message, mtError, [mbOk], 0); end; end;
简化测试代码(仍报错)
ADOQuery1.Edit; ADOQuery1BEZEICHNG.Value := 'Hello'; ADOQuery1.Post;
补充信息
- ADOConnection连接字符串:
Provider=MSDASQL.1;Persist Security Info=False;Extended Properties="CollatingSequence=ASCII;DefaultDir=J:\ROBERT\DATABASE;Deleted=0;Driver={Microsoft dBase-Treiber (*.dbf)};DriverId=277;FIL=dBase IV;FILEDSN=C:\Users\User\Documents\ABzuFA.dsn;MaxBufferSize=2048;MaxScanRows=8;PageTimeout=5;SafeTransactions=0;Statistics=0;Threads=3;UID=admin;UserCommitSync=Yes;";Initial Catalog=J:\ROBERT\DATABASE - 加载数据的SQL语句:
Select * from Orders - 测试情况:在另一小型DBF数据库上运行相同代码可正常编辑,仅目标数据库出现该问题
解决方案
1. 给DBF表添加主键/唯一索引
DBF驱动更新记录时需要唯一标识定位行,若表无主键或唯一索引,驱动无法精准匹配要更新的行。给Orders表添加主键(如订单ID类唯一字段)或唯一索引。
2. 调整连接字符串参数
在连接字符串的Extended Properties中添加Exclusive=1,以独占模式打开数据库,避免其他进程同时修改数据导致行版本不一致:
Provider=MSDASQL.1;Persist Security Info=False;Extended Properties="CollatingSequence=ASCII;DefaultDir=J:\ROBERT\DATABASE;Deleted=0;Driver={Microsoft dBase-Treiber (*.dbf)};DriverId=277;FIL=dBase IV;FILEDSN=C:\Users\User\Documents\ABzuFA.dsn;MaxBufferSize=2048;MaxScanRows=8;PageTimeout=5;SafeTransactions=0;Statistics=0;Threads=3;UID=admin;UserCommitSync=Yes;Exclusive=1;";Initial Catalog=J:\ROBERT\DATABASE
3. 显式通过主键定位记录
避免依赖RecNo定位行,改用主键字段重新定位后再编辑:
procedure TForm3.BtnEditClick(Sender: TObject); var iReplacement : string; PrimaryKeyValue: Variant; begin // 假设主键为第一个字段,根据实际表结构调整 PrimaryKeyValue := ADOQuery.Fields[0].Value; iReplacement := InputBox('值', '修改字段 "' + DBGrid1.Columns[selectedCol].Field.FieldName + '" 的值:' + ADOQuery.Fields[0].AsString + ', ' + ADOQuery.Fields[2].AsString, ADOQuery.Fields[selectedCol].AsString); try // 重新定位到目标记录 ADOQuery.Locate(ADOQuery.Fields[0].FieldName, PrimaryKeyValue, []); ADOQuery.Edit; ADOQuery[DBGrid1.Columns[selectedCol].Field.FieldName] := iReplacement; ADOQuery.Post; except on E: Exception do MessageDlg('错误: ' + E.Message, mtError, [mbOk], 0); end; end;
4. 检查并修复DBF表损坏
使用DBF专用修复工具(如dBase自带工具或第三方工具)检查Orders.dbf,若表结构或数据存在损坏,修复后再尝试更新。
5. 更换DBF访问组件
尝试使用Borland原生TDBF组件替代ADO连接,部分情况下原生组件对旧版DBF格式的兼容性更好。
内容的提问来源于stack exchange,提问作者Robert
相关产品推荐
相关产品推荐

