OID产生方式 |
|
mustapha.wang
資深會員 發表:89 回覆:409 積分:274 註冊:2002-03-13 發送簡訊給我 |
为了弹性一般的资料表都用一个OID来作为主Key,而不采用有意义的可能修改的xx代号之类。SQL server有一种自动增加的Field,但对Master-detail来说可能不满足需要,在Client,detail表是马上需要Master表的key的,不能先存了master,产生了key,再来编辑detail,把key给它(有些状况不允许只有master而没有detail资料;有些状况是Master还没编辑好,就要新增detail)。 我一般这样做,用一个OID的资料表来记录每个Table的当前流水号,每次产生一个就增加1,如
TableName CurValue
Table1 1
Table2 8 1 Query1.SQL.Text:='select * from OID where TableName=''xxx''';
2 Query1.Open;
3 Query1.Edit;
4 Query1.FieldByName('CurValue').asInteger:=Query1.FieldByName('CurValue').asInteger+1;
5 Query1.Post; 关键是多人使用时,如何避免重复,如果User1运行到第3行时(如CurValue为5),User2来了,它运行完(选到的CurValue也是5,最后修改成了6),再换到User1来运行,它也企图修改成6,但是会失败(update OID... where CurValue=5)。因此需要在User查询出资料后,锁定这些资料,不要让User2读到,只有User1完成更新后,user2才能读出。这个排他锁可以用XLOCK,如果单独用,它是最小粒度---行锁,我们不需要加表锁TABLOCK来锁住整个OID表。
procedure TForm1.BitBtn2Click(Sender: TObject); var i:integer; begin ADOConnection2.Open; try for i:=1 to 30 do begin ADOConnection2.BeginTrans; try ADOQuery2.Close; ADOQuery2.SQL.Text:='select TableName,CurValue from OID'+ ' with (XLOCK) where TableName=''CalendarGroup'''; ADOQuery2.Open; Memo1.Lines.Add(InttoStr(i)+':'+ADOQuery2.FieldByName('CurValue').AsString); Sleep(500);//停停,让别的线程有机会来打断它 ADOQuery2.Edit; ADOQuery2.FieldByName('CurValue').asInteger:= ADOQuery2.FieldByName('CurValue').asInteger+1; ADOQuery2.Post; ADOConnection2.CommitTrans; except ADOConnection2.RollbackTrans; Raise; end; end; finally ADOConnection2.Close; end; end;这里注意XLOCK需要在一个Transaction中,直到这个Transaction完才释放。你可以打开多个exe,同时执行上面的动作,看看锁不锁与开不开始Transction的效果。 久病成良医--多试 千人之诺诺,不如一士之谔谔--兼听
------
江上何人初见月,江月何年初照人
附加檔案:47879_Lock.rar
|
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |