delphi事务丢失的问题 |
答題得分者是:HikaruGo
|
tangfengsh
一般會員 ![]() ![]() 發表:5 回覆:3 積分:1 註冊:2008-11-10 發送簡訊給我 |
客户端是delphi+sql2005,都是单机,不存在并发的问题,在许多客户那边都出现这种主表没有纪录,细表又有记录的情况,一个月大概会出现几条,我自己测试时怎么测也出不来这种数据.
还有的是他们在同一单里执行删除细表记录的操作,全删完后再执行插入操作,结果删除的记录在数据库中还是有. 感觉很奇怪,在DBGRID里明明是有这条记录,删的时候也是用qryGetRCKMX0.fieldbyName('明细ID')去删的,结果DBGRID没显示,数据库里又没有删掉.(这种数据只在客户那边有) 一般是这样,主表记录是ID,DH,... 细表记录是 第一条细表记录:细表ID,主表ID-1,DH,... ,第二条:细表ID 1,主表ID-1,DH...第二条:细表ID 2,主表ID,DH... 把代码贴出来,希望有人能帮我解答,不知道是不是事务的问题还是同一个ADO的问题,谢谢,加分. 主表 主键ID为自动增长,DH为单号(取主表里DH的最大值 1) 在保存按钮里用事务控制.第一次保存根据ID.text是否为空,为空的话用单号.text 插主表,取出刚插的记录的ID. try frmDB.ADOConnection1.BeginTrans; if trim(ID.text) = '' then begin with qryGetTmp do begin close; sql.clear; sql.add(' insert into 主表(DH,...'); execSQL; close; sql.clear; sql.add(' select ID from 主表 where DH = ' '单号'); open; ID.text=fieldByName("ID").asString; end; end; with qryGetTmp do begin close; sql.clear; sql.add(' insert into 细表(主表ID,主表DH,..) values( '); sql.add(ID.text ',' ',' '''' edRCKDH0.text ''''...) '); execSQL; close; with frmDB.qryCMD do begin close; sql.clear; sql.add('更新库存的SQL语句'); execSQL; close; end; end; with frmDB.qryCMD do begin close; sql.clear; sql.add('更新主表的语句'); //插完细表再更新主表 execSQL; close; end; frmDB.ADOConnection1.CommitTrans; except on e: exception do begin MsgBox('错误', '数据操作失败!' e.message, ''); frmDB.ADOConnection1.RollbackTrans; exit; end; end; RefreshRCKMX; //刷新明细信息; 右边的DBGRID绑定的是 qryGetRCKMX0 procedure TfrmKC_YPLS.RefreshRCKMX; //刷新明细; if trim(ID.text) = '' then begin qryGetRCKMX0.close; exit; end; with qryGetRCKMX0 do begin close; sql.clear; sql.add(' select a.*,c.ypsl00 as kcsl00,' '''' edyprkdh.Text '''' ' as rkdbh0 from 细表 a,主表 b,库存 c '); sql.add(' where a.ID=b.ID and a.单号=c.单号 and a.ID= ' ID.text); open; end; with qryGetTmp do begin close; sql.clear; sql.add(' select sum(yppfj0*ypsl00) as hjje00 from 细表 where rckid0 = ' ID.text); open; edCFZJE0.text:=FormatFloat('0.0',fieldByname('hjje00').asFloat); close; end; 删除按钮的函数: if trim(qryGetRCKMX0.fieldbyName('RCMXID').asString) = '' then begin //明细表没有数据,但主表有数据,直接把主表的数据也删除掉. if trim(ID.text) <> '' then begin ExecuteSQL('delete from 主表 where ID= ' ID.text); edRCKDH0.text:=''; ID.text:=''; end; exit; end; //否则,要修改相关的库存信息. with frmDB.qryCMD do begin close; sql.clear; sql.add('修改库存的语句'); execSQL; close; end; with qryGetTmp do begin close; sql.clear; sql.add(' delete from 细表 where RCMXID = ' qryGetRCKMX0.fieldbyName('RCMXID').asString); execSQL; end; RefreshRCKMX; //刷新入出库明细; qryGetRCKMX0,qryGetTmp,frmDB.qryCMD连接都是用的是frmDB.ADOConnection1 ADOConnection1的connectOption是 coAsyncConnect,IsolationLevel是ilCursorStability,MODE是cmShareDenyNone不知道有没有影响 我的DH是根据主表的最大值 1,生成的.有DH.text,只读,谢谢你回复 在点新单时. with qryGetTmp do begin close; sql.clear; sql.add(' select max(cast(dh as int)) as dh from 主表); open; if fieldByname('dh').asString='' then DH.text:='1' else DH.text:=IntToStr(strToInt(fieldByname('dh').asString) 1); end; 在我机子上怎么点新单,保存,删除,都不会出现客户那边的状况,都是单机 删除是根据qryGetRCKMX0.fieldbyName('RCMXID').asString 就是根据细表的ID插的,删完执行RefreshRCKMX; //刷新明细的函数; 到最后一条删完时刷新,DBGRID是显示没有数据的,此时再点删除的话才会删主表里的记录 也就是删除没和单号有关系. 另外,问题是这样的,主表里只有ID2530的记录,没有ID为2529的记录,主表的历史记录表里也没有 主表 里的记录: ID DH .. 2530 1266 .. 主表的历史记录表(用触发器操作,主表插入,更新时都会在历史表里插入一条记录) ID DH .. 2530 1266 .. 2530 1266 .. 2530 1266 .. 2530 1266 .. 细表 里的记录: 细表ID 主表ID 单号 10745 2529 1266 10746 2529 1266 10747 2530 1266 10748 2530 1266 细表的历史记录与细表一样.(分析是没有做细表的删除操作.) 这种记录在每个客户那里都有,有些说只是执行了保存,最后完成,有些是执行了保存,还有执行了删除操作(在DBGIRD里看到是删掉了,在数据库里又没有删掉,细表的历史记录表也是只有插入的操作) 忘高手指点一下 編輯記錄
tangfengsh 重新編輯於 2008-11-10 13:29:17, 註解 無‧
|
P.D.
版主 ![]() ![]() ![]() ![]() ![]() ![]() 發表:603 回覆:4038 積分:3874 註冊:2006-10-31 發送簡訊給我 |
|
tangfengsh
一般會員 ![]() ![]() 發表:5 回覆:3 積分:1 註冊:2008-11-10 發送簡訊給我 |
|
HikaruGo
中階會員 ![]() ![]() ![]() 發表:22 回覆:69 積分:88 註冊:2007-12-09 發送簡訊給我 |
1.MASTER DETIAL 第一要設關聯 MASTER (習慣給個自動給號欄位 EX: M_KEY) Detial.FK_M_Key FK Masetr.M_Key 那樣不會有不合法的資料 2.Insert 善用變數取出剛輸入的給號數值,不要使用MAX() MSSQL .,SQL: Insert Master Values( .... ) 多一句 SELECT @Ident... as idx @Ident :要看一下SQL HELP idx:最後的一筆資料 (M_KEY) 使用MAX(M_Key) 一定會有問,多人使用鐵定掛 (因會會抓錯) M_KEY = idx 3. DELETE DELETE DETIAL WHERE FK_M_KEY = idx DELETE MASTER FK_M_KEY = idx |
tangfengsh
一般會員 ![]() ![]() 發表:5 回覆:3 積分:1 註冊:2008-11-10 發送簡訊給我 |
谢谢HiKaruGo迴複.
1.我認為,設了關聯,還是會出現這种問題,因為在事務開始時,是先插主錶,再根據單號取剛才插的那條ID,(細錶里的記錄也顯示此時ID已取出來了),然後再插細錶,也就是插主明細時符合外鍵約束. 2.SELECT @Ident... as idx ,這個ID用我的方法是正确取出來了,且正確的插入到細錶中,而且我的主錶添了個觸髮器,用來插歷史記錄錶. 3. 我的MAX()只是用來取主錶中單號的最大值,最后再加1,确保不重複,多人訪問時,是會出錯,但是我用了惟一索引確保單號的惟一性. 3.DELETE,我要實現的是細錶一條條記錄刪,我上麵說了,DBGRID里顯示已經刪除,而且語句是用細錶的主鍵ID=qryGetRCKMX0('rcmxid')來刪的.DBGRID顯示沒有,數据庫中又有.(當然,我自己測試一直很正確,就是客戶那里用瞭一兩個月出來十條左右上麵那种數据.) 再次感謝HIKARUGO的回復,不知道能不能把這個問題解決呢.? ===================引 用 HikaruGo 文 章=================== 1.MASTER DETIAL 第一要設關聯 MASTER (習慣給個自動給號欄位 EX: M_KEY) Detial.FK_M_Key FK Masetr.M_Key 那樣不會有不合法的資料 2.Insert 善用變數取出剛輸入的給號數值,不要使用MAX() MSSQL .,SQL: Insert Master Values( .... ) 多一句 SELECT @Ident... as idx @Ident :要看一下SQL HELP idx:最後的一筆資料 (M_KEY) 使用MAX(M_Key) 一定會有問,多人使用鐵定掛 (因會會抓錯) M_KEY = idx 3. DELETE DELETE DETIAL WHERE FK_M_KEY = idx DELETE MASTER FK_M_KEY = idx |
shunchia63
高階會員 ![]() ![]() ![]() ![]() 發表:26 回覆:141 積分:198 註冊:2007-05-22 發送簡訊給我 |
你沒設 FK 當然會有此現像(Detial 有Master沒有),
至於你Detial delete 你可以使用 TADOCommand.Execute ,不要用 TQuery function Execute(var RecordsAffected: Integer; const Parameters: OleVariant): _RecordSet; overload; 透過RecordsAffected 應該= 1 若 =0 當然發生一些事 , Trigger Rule 也有可能要Check 一下CODE. |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |