批量添加数据时出错? (100分)

  • 主题发起人 Frank001
  • 开始时间
F

Frank001

Unregistered / Unconfirmed
GUEST, unregistred user!
我用loadfromfile读入savetofile是生成的文件,到ADODataSet1,
然后构造SQL语言添加到access数据库中,每次添加到第十三条时就出错,
提示的意思大致是说要添加的记录的主键和表中已有的数据的主键重复,
但明明是没有重复啊。
我写了一句代码显示不能添加时,那条要添加的记录的主键的值,发
现刚刚好是上一条添加的记录的值,但这条记录的主键的值明明不是这个
值啊。
更怪的是,在调试模式下,然后在过程中设置断点,进行运行,却可
以完全添加完成,到第十三条时也没有问题。真是怪了
以下是程序代码:
procedure TFormF.ToolButton5Click(Sender: TObject);
var
sqlstr,eid:string;
i:integer;
begin
if ADODataSet1.CommandType = cmdFile //如果还在file数据库状态,就更新
then
begin
ADODataSet1.First; //到第一条数据
while not ADODataSet1.Recordset.EOF do
begin
sqlstr:='insert into';
sqlstr:=sqlstr+' T_c(c_1,c_2,c_3,c_4,c_5,c_6,c_7,c_8,c_9,c_10,c_11,c_12,c_13)';
sqlstr:=sqlstr+' values:)c1,:c2,:c3,:c4,:c5,:c6,:c7,:c8,:c9,:c10,:c11,:c12,:c13)';
ADOComadd.CommandText:=sqlstr;
ADOComadd.Parameters.ParamByName('c1').Value:=ADODataSet1.Recordset.Fields.Item['c_1'].Value;
ADOComadd.Parameters.ParamByName('c2').Value:=ADODataSet1.Recordset.Fields.Item['c_2'].Value;
ADOComadd.Parameters.ParamByName('c3').Value:=ADODataSet1.Recordset.Fields.Item['c_3'].Value;
ADOComadd.Parameters.ParamByName('c4').Value:=ADODataSet1.Recordset.Fields.Item['c_4'].Value;;
ADOComadd.Parameters.ParamByName('c5').Value:=ADODataSet1.Recordset.Fields.Item['c_5'].Value;
ADOComadd.Parameters.ParamByName('c6').Value:=ADODataSet1.Recordset.Fields.Item['c_6'].Value;
ADOComadd.Parameters.ParamByName('c7').Value:=ADODataSet1.Recordset.Fields.Item['c_7'].Value;
ADOComadd.Parameters.ParamByName('c8').Value:=ADODataSet1.Recordset.Fields.Item['c_8'].Value;
ADOComadd.Parameters.ParamByName('c9').Value:=ADODataSet1.Recordset.Fields.Item['c_9'].Value;
ADOComadd.Parameters.ParamByName('c10').Value:=ADODataSet1.Recordset.Fields.Item['c_10'].Value;
ADOComadd.Parameters.ParamByName('c11').Value:=ADODataSet1.Recordset.Fields.Item['c_11'].Value;
ADOComadd.Parameters.ParamByName('c12').Value:=ADODataSet1.Recordset.Fields.Item['c_12'].Value;
ADOComadd.Parameters.ParamByName('c13').Value:=ADODataSet1.Recordset.Fields.Item['c_13'].Value;
try
ADOComadd.Execute; //执行添加记录语句
except
eid:=ADODataSet1.Recordset.Fields.Item['c_1'].Value;
showmessage('添加到第'+inttostr(i+1)+'信息时出错!id='+eid);
exit; //退出批量添加过程
end;
i:=i+1;
ADODataSet1.next;
end; //while end
showmessage('共有'+inttostr(i)+'条纪录被添加。');
end; // then end
end;
这到底是什么原因啊,可以解决吗?
 
我调试了好久还是找不出问题的原因,难道是Delphi5的BUG。[?][?][?]
 
up
有高手帮帮忙吗?
 
这当然不是DELPHI的问题, 如果你用VB做
一样会遇到!
原理大概是这样的: access插入记录时首先
写入空白记录, 再改写空白记录的内容, 如果你
连续插入记录太快, 就会出现两条空白记录的情况
它们的主键当然重复.
想最简单的实现, 只要在你的代码中插入一个
延时命令就可以了,但是这样不是最好的办法,记录多
时依然会出问题.
应该使用批量更新的命令, 就像ado中的update
batch 方法一样.
还有一种方法,就是每写入一个记录便将缓冲区
内容写入硬盘(使用ado中对象方法)
或者判断当前dataset中记录状态好象也可以
具体方法,因为我没有使用DELPHI操作数据库,所以
容我有时间再回答.
 
如果是sql server数据库,一点儿问题也没有
但access不支持每句用分号隔开,只能一条一条地执行了
 
to fatbug:
我在调试的时候,发现重复的主键值,并不是空的,而是上一条记录主键的值,
这一点我在问题中已经说明。
因为在设置了断点进行运行,是可以完全添加,因此起先我的猜测也是和你有
些类似,以为加的太快了,每添加一条,就用sleep(1000)进行延时,一分钟够
长吧,可还是有同样的问题。
因此,我认为你说的原理应该是不对的。

其实设置了断点进行运行,可以完全添加,正常情况却不行,这才是我最想不
通的地方。至于用其它的方法进行添加,倒是有不少。
fatbug,你如果有时间的话,倒是可以再探讨探讨
 
to NewLearner:
你的话,我不是很明白哦,“不支持每句用分号隔开”,你说的时SQL语句吗,
我可也是一句一句执行的哦,你可以再看看源码。
 
用延时,搞什么搞?
你的sql语句中不加参数的时候你试过没
 
呵呵,楼上的,你也不用这么生气嘛,
用延时也只是为了调试用的啊,实际中想快还来不及呢,还延时。
 
to popewh:
刚刚试过不用参数,直接生成sql语句,但问题还是依旧,
在 ADOComadd.Execute; 处设个断点,没有问题。
不设断点直接运行,就会出现上面说的问题。
真实邪门了。
 
还有如果添加的记录少于13条,就会在添加最后一条时出现上面的问题。
 
惭愧,惭愧,汗颜!
这个问题以前用VB编程时遇到过的,所以
楼主的帖子还没有看仔细就乱发贴了, 抱歉!
尽快研究后与大家探讨!
 
不妨试一下: 每次执行后检查一下adoCommand的
state, 直到当前状态 不是stExecuting, 才继续执行
 
我刚才用你说的方法试了一下,还是不行,
在执行添加语句的出错时,之前的states的值也为stClosed,而不是stExecuting,
因此估计不会是这个问题。
我觉得到可以从“设断点执行没有问题。不设断点直接运行,就会出问题”的现象着手。
之前我分析一下原因,得出的一个结论是:有可能是连续插入记录太快,不过已经被我
的延时测试给否决的。

大家可以再想想,问题到底再哪里。
 
你用FieldByName一条一条试,看是否出问题
 
楼上的方法很有效,我刚刚试过

ADOComadd.Parameters.ParamByName('c1').Value:=ADODataSet1.Recordset.Fields.Item['c_1'].Value;
……
都改为
ADOComadd.Parameters.ParamByName('c1').Value:=ADODataSet1.FieldByName('c_1').Value;
……
就ok啦,不过一些慢,谢谢popewh啦。
不过,我最想知道的倒是以前那样的方法为什么在debug时可以,正常运行时却不行。
大家可以再探讨探讨啊。
 
ADODataSet1.Recordset不可信,RecordCount有时候都不准
 
顶部