線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:1412
推到 Plurk!
推到 Facebook!

delphi事务丢失的问题

答題得分者是:HikaruGo
tangfengsh
一般會員


發表:5
回覆:3
積分:1
註冊:2008-11-10

發送簡訊給我
#1 引用回覆 回覆 發表時間:2008-11-10 13:28:01 IP:221.122.xxx.xxx 訂閱
客户端是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

發送簡訊給我
#2 引用回覆 回覆 發表時間:2008-11-10 13:32:30 IP:219.68.xxx.xxx 未訂閱
沒有很細看你的code, 不過一般我們的經驗, master-detail的資料結構
插入時, 先新增主表, 再新增明細
刪除時, 先刪除明細, 再刪除主表
tangfengsh
一般會員


發表:5
回覆:3
積分:1
註冊:2008-11-10

發送簡訊給我
#3 引用回覆 回覆 發表時間:2008-11-10 13:41:15 IP:221.122.xxx.xxx 訂閱
謝謝,我上麵也是這樣子的,插入主錶和細錶時在同一事務中,事務開始,先插主錶,再取主錶的自增長ID,再插細錶,最后提交。
可是就會出現上麵的問題。而且我自己在本地怎麼測都不會出現。
===================引 用 P.D. 文 章===================
沒有很細看你的code, 不過一般我們的經驗, master-detail的資料結構
插入時, 先新增主表, 再新增明細
刪除時, 先刪除明細, 再刪除主表
HikaruGo
中階會員


發表:22
回覆:69
積分:88
註冊:2007-12-09

發送簡訊給我
#4 引用回覆 回覆 發表時間:2008-11-10 14:15:59 IP:61.62.xxx.xxx 訂閱

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

發送簡訊給我
#5 引用回覆 回覆 發表時間:2008-11-10 19:53:38 IP:122.198.xxx.xxx 訂閱
谢谢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

發送簡訊給我
#6 引用回覆 回覆 發表時間:2008-11-11 00:46:02 IP:61.62.xxx.xxx 訂閱
你沒設 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.


系統時間:2024-05-03 6:09:52
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!