Adoconnection,Adoquery,事务控制失败,高手请进!!!(300分)

  • 主题发起人 主题发起人 IT书生
  • 开始时间 开始时间
I

IT书生

Unregistered / Unconfirmed
GUEST, unregistred user!
Adoconnection,Adoquery,事务中有update,insert,但update无效。以下是部份代码:
(1)开始事务部份
procedure TFrmYwglKdCzgrjf.BkdClick(Sender: TObject);
begin
.....
frmdm.ADOConn.BeginTrans;
if kd then begin //kd为函数。
frmdm.ADOConn.CommitTrans;
Application.MessageBox('开单成功,请进行打印操作!', '提示信息', mb_ok or mb_iconinformation);
end else begin
frmdm.ADOConn.RollbackTrans;
Application.MessageBox('开单失败!', '提示信息', mb_ok or mb_iconinformation);
end;
end;
(2)KD函数,主要进行数据操作。
function TFrmYwglKdCzgrjf.KD: boolean;
var
wherestr1:string;
begin
Result := True;
try
wherestr1:=' where grbh='+inttostr(grbh)+' and djh=0 and sfczdj=''是'' and sfgrzhbj=''否''';
with frmdm.ADOQ1 do
begin
close;
sql.Text := 'insert into djh(ybnd,kdlxbh,kdsj,kdczy,ms,sfylr) values(' + l7.Caption + ',13,''' + l2.Caption + ''',''' + l18.Caption + ''',''' + trim(edit2.text) + ''',''否'')';
execsql;
sql.Text := 'select @@identity'; //得到序号
open;
G_djh := fields[0].AsInteger;
close;
sql.Text := 'update zjjhmx set djh=' + inttostr(G_djh)+''+ wherestr1;
execsql; //此处在事务执行完后,数据没有更新!!!!
G_CountNum(G_djh);//调用计算函数,
close;
sql.Clear;
sql.Add('insert into jffzdj(djh,ybnd,dwbh,zje,gryj,dwyj,znj,tcyj,dwhrzh,zhyj,zhkjdbtc,zhsj,sfczdj,sfbj)');
sql.Add('values('+ inttostr(G_djh) + ',' + inttostr(G_Ybnd) + ',' + inttostr(dwbh) + ',' + floattostr(G_zje+G_znj) + ',');
sql.Add(''+floattostr(G_gryj) + ',' + floattostr(G_dwyj) + ',' + floattostr(G_znj) + ',');
sql.Add(''+floattostr(G_tcyj) + ',' + floattostr(G_dwhrzh) + ',' + floattostr(G_zhyj) + ',');
sql.Add(''+floattostr(G_zhkjdbtc) + ',' + floattostr(G_zhsj) + ',''否'','''+G_sfbj+''')');
execsql; //此处在事务的执行后,数据库有记录。
end;
except
Result := False;
end;
end;
(3)计算函数:
procedure TFrmYwglKdCzgrjf.G_CountNum(djh: integer);
begin
with frmdm.ADOQtmp do
begin
close;
sql.Text := 'select sum(gryj),sum(dwyj),sum(tcyj),sum(dwhrzh),sum(zhyj), sum(zhkjdbtc),sum(zhsj) from zjjhmx where djh=' + inttostr(djh) + '';
open;
G_gryj := fields[0].AsFloat;
G_dwyj := fields[1].AsFloat;
.......
close;
sql.Text:='select dwbh from gr where bh='+inttostr(grbh)+'';
open;
dwbh:=fields[0].AsInteger;
end;
end;
以上是事务执行的全部代码,以前的贴子也都差不多查了,请有相似经验的,经验丰富的
高人出手,在此先行谢过了。 ^_^
 
很简单的办法 前端工具的事物不可靠
用后端数据库的事物 一定没有问题
试试
 
其实放到存储过程里控制事务会好些,不过没办法,头让这么做的。这样做的好处是可以
方便地转到ORACLE数据库。
 
update_sql无效是因为没有满足条件的记录,你看看
sql.Text := 'select @@identity'; //得到序号
open;
G_djh := fields[0].AsInteger;
这几句返回的值是否正确!
 
to 荷塘新月:
正确的,我已经单步执行了所有的代码,就是找不到错误的地方,你说的
G_djh := fields[0].AsInteger 已经得到值了,而且在update语句后如果再加上:
close;
sql.Text := 'select count(*) from zjjhmx where djh=' + inttostr(G_djh) + '';
open;
if fields[0].asinteger = 0 then begin Result := False; exit; end;
结果是在事务内部 update已经修改了记录,并且在内部能select出来修改的记录数。
 
会不会有一些触发器之类的东西修改你要update的那个表?否则应该不会该不掉的啊
 
看你的frmdm.ADOQ1.LockType是不是这个值:ltBatchOptimistic,如果不是缓存的问题
的话,你就再把改变SQL的地方用 close; sql.Clear; 试试。
不过,看起来问题还真奇怪呀。
 
先谢谢二位了
to wdl:没有建触发器。
to wumeng:试了,还是不行。
可我另外写建一新工程,同样写事务,包括以上相同功能的语句,就可以,但这段代码为
什么不行呢,奇怪。。。。。
 
把你的query删掉,添加一个空白的,当然要设置一些参数了...
这种无厘头办法也许好使.......
 
这种情况我也遇到过,如果不用事务处理就会得到预期的结果,真是不懂。
 
前端的事务几乎不能用,问题还不止这一个呢。
 
to wdl:我用的query是全局的,应该没问题,设置一些参数,有没有特别的地方?
to DJ:你好,真的是这样,不用事务,一切OK,没办法!
to 小黄鱼:不会吧,前端的事务也常用的,如果这样。。。。

以下是我用sqlserver的profiler跟踪调试的结果:ADOCONN就一个,在程序开始时连接。
开始事务后,进行INSERT ,UPDATE 都正常,但到了下面:
+RPC:Completed sp_prepare @P1 output, NULL, N'select sum(gryj)as gryj,
sum(dwyj)as dwyj,sum(tcyj) as tcyj,sum(dwhrzh) as dwhrzh,
sum(zhyj) as zhyj,sum(zhkjdbtc) as zhkjdbtc,sum(zhsj) as
zhsj from zjjhmx where djh=182 ', 1 select @P1
+RPC:Completed sp_unprepare
+SQL:BatchCompleted select sum(gryj)as gryj,sum(dwyj)as dwyj,sum(tcyj) as
tcyj,sum(dwhrzh) as dwhrzh,sum(zhyj) as zhyj,
sum(zhkjdbtc) as zhkjdbtc,sum(zhsj) as zhsj from zjjhmx
where djh=182
Connec //又建立连接,奇怪!!! 难道与SUM语句有关???
ExistingConnection
+SQL:BatchCompleted SET NO_BROWSETABLE ON
+RPC:Completed sp_prepare @P1 output, NULL, N'SELECT * FROM zjjhmx',
1 select @P1
Disconnect //断开连接, SELECT * FROM zjjhmx这句话从来没用,怎么会出现在这里???

这问题困扰我几天了,没办法,DELPHI真叫人又爱又恨!!!
 
你用的是SQL SERVER 7吗?
如果是打上补丁试一下。
以前我碰到过类似情况,打上SQL SERVER 7 SP2就好了。
 
把原先的ADOConnection干掉,重新加入一个ADOConnection,并配置它,试试!
 
to 草央包包: 在SQLSERVER2000上也不行。
to white83:已经把ADOCONNECTION干掉N次了,呵呵
另外建新工程,写相似语句就可以,但把这段代码分出去就不行,是否与数据库结构有关。
重新建表后,仍是这样,真的没办法了吗。。。。。。。
 
TO IT书生:
我以前遇到过这样的问题:用户输入一条记录,然后我根据用户的输入生成三条记录,
我用的是 ADODataSet.Edit;
ADODataSet.FieldByName('stat').value:='Y';
ADODataSet.DataSet.Post;
这样简单的语句,想重复生成某个栏位不同值的三条记录,就不行,后来我新作了个程序,
专门来试这个,TABLE也是用的这个。就能通过。
后来,我只好用SQL语句(ADOQUERY)作了。
也就是说,我是绕过了这个错误。。。
 
在这一个事务处理过程中
sql.Text := 'select @@identity'; //得到序号
open;
G_djh := fields[0].AsInteger;
这时得到的G_djh是为提交的(脏读),可能是因为这个原因使你在
sql.Text := 'update zjjhmx set djh=' + inttostr(G_djh)+''+ wherestr1;
execsql; //此处在事务执行完后,数据没有更新!!!
无法更新。
 
to wumeng:我用的就是query,没办法绕过啊 ^_^
to DJ:我用的测试用例,就可以的,所以我想问题应该不是在这,我个人认为在一个事务
里是可以读数据的。在事务外才是脏读,不知对否。
我又写了例子测试:
procedure TForm1.Button1Click(Sender: TObject);
var
djh,tmp:integer;
begin
ADOConnection1.BeginTrans;
try
with Adoquery1 do
begin
close;
sql.Clear;
sql.Add('insert into test2(yx) values(''a'')');
sql.Add('select @@identity');
open;
djh:=fields[0].AsInteger;
close;
sql.Text:='update test3 set djh='+inttostr(djh)+' where num=4';
Execsql;
close;
sql.Text:='select * from test3 where num=4';
open;
if recordcount=0 then
begin
showmessage('no record');
form1.ADOConnection1.RollbackTrans;
Exit;
end;
close;
sql.Text:='select sum(num) from test3 where num=4';
open;
tmp:=fields[0].AsInteger;
close;
sql.Text:='insert into test4(djh,con) values('+inttostr(djh)+','+inttostr(tmp)+') ';
Execsql;
end;
form1.ADOConnection1.CommitTrans;
except
form1.ADOConnection1.RollbackTrans;
showmessage('rollback data');
end;
end;
实现的功能与上面的一样,可这个就行,所以我怀疑是数据库设计的问题,又重建了表
可还是不行,在我程序其它地方用事务就可以的,就这个地方不行。
另外,我在最后INSERT 语句之前提交事务就可以。真是招都用完了 @_@

 
>>>to wumeng:我用的就是query,没办法绕过啊 ^_^
这个我知道,我说的是:DELPHI作的程序,有时候行,有时候就不行(通不过或结果
不对)。感觉让人很奇怪。
我的重点在说这个:(这样简单的语句,想重复生成某个栏位
不同值的三条记录,就不行,后来我新作了个程序,专门来试这个,
^^^^^^^^
数据库中的TABLE也是用的同一个。就能通过。)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
我在SQL2K中测试了这个,它能通过,看来这又是DELPHI的错误了。。。
declare @id int
BEGIN TRAN T1
INSERT INTO jobs (job_desc,min_lvl,max_lvl)
VALUES ('Accountant',12,125)
SELECT @id=@@IDENTITY
update employee set Job_id =@id where emp_id='PMA42628M'
COMMIT TRAN T1
还有,你一步步的追踪,看中间结果对不对。或者象李维说的,运行DELPHI程序,
同时用SQLSERVER的工具MS Profiler,看它是不是在一个事务中。(好象现在只有试了。。。)
 
将这段代码用profiler跟踪结果完整的贴出来看看。
 
后退
顶部