全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:4743
推到 Plurk!
推到 Facebook!

如何在Ms sql server 中實現Oracle 中的 For Update Nowait 功能?

答題得分者是:Mickey
agilehawk
一般會員


發表:3
回覆:10
積分:7
註冊:2008-09-05

發送簡訊給我
Mickey
版主


發表:77
回覆:1882
積分:1390
註冊:2002-12-11

發送簡訊給我
#2 引用回覆 回覆 發表時間:2008-09-12 14:10:06 IP:218.163.xxx.xxx 訂閱
你好:

試試看

select * from patient with (HOLDLOCK) where patientid =111
agilehawk
一般會員


發表:3
回覆:10
積分:7
註冊:2008-09-05

發送簡訊給我
#3 引用回覆 回覆 發表時間:2008-09-12 23:33:59 IP:119.4.xxx.xxx 訂閱

===================引 用 Mickey 文 章===================
你好:

試試看

select * from patient with (HOLDLOCK) where patientid =111


此種方法已經試用過,不能得到想要的結果,還是會同時允許修改,并且后提交的將先提交的給覆蓋掉了。
OsX
版主


發表:6
回覆:151
積分:111
註冊:2003-05-03

發送簡訊給我
#4 引用回覆 回覆 發表時間:2008-09-13 11:11:22 IP:219.84.xxx.xxx 未訂閱
select * from XXX with ( XLOCK, NOWAIT) where 1 = 1
編輯記錄
OsX 重新編輯於 2008-09-13 11:12:01, 註解 無‧
agilehawk
一般會員


發表:3
回覆:10
積分:7
註冊:2008-09-05

發送簡訊給我
#5 引用回覆 回覆 發表時間:2008-09-15 07:29:11 IP:119.4.xxx.xxx 訂閱

===================引 用 OsX 文 章===================
select * from XXX with ( XLOCK, NOWAIT) where 1 = 1

此種方法已經試用過,不能得到想要的結果,還是會同時允許修改
Mickey
版主


發表:77
回覆:1882
積分:1390
註冊:2002-12-11

發送簡訊給我
#6 引用回覆 回覆 發表時間:2008-09-15 08:19:40 IP:218.163.xxx.xxx 訂閱
MSSQL ISQL 與 ORACLE PLSQL...還是有差別

for update nowait...與 holdlock...確實也不太一樣.

以前我是用 SQL 檢查該 Table 是否有被其他程序 Lock...並且配合 Transaction 的使用

參考看看囉

function LockBDEDataSet(DS : TQuery):boolean;
var fsql,DBType,fTableName,fHostName: string;
t:hDBICur;
r:DBIResult;
OldInTran : Boolean;
begin
if not DS.Active then raise Exception.CreateFmt('DataSet %s is not actived.',[DS.Name]);
DBType := DS.Database.Session.GetAliasDriverName(DS.Database.AliasName);
fTableName := GetTableNamefromSQL(DS.SQL.Text);
if CompareText(DBType,'Oracle')=0 then
fsql := DS.SQL.Text ' for update nowait'
else if CompareText(DBType,'MSSQL')=0 then
fsql := StringReplace(DS.SQL.Text,fTableName,fTableName ' with (HOLDLOCK)',[rfReplaceAll, rfIgnoreCase])
else if CompareText(DBType,'SYBASE')=0 then
fsql := StringReplace(DS.SQL.Text,fTableName,fTableName ' HOLDLOCK',[rfReplaceAll, rfIgnoreCase])
else raise Exception.CreateFmt('Unsupported DBMS %s.',[DBType]);
OldInTran := DS.Database.InTransaction;
if not DS.Database.InTransaction then DS.Database.StartTransaction;

r := DbiQExecDirect(DS.Database.Handle,qrylangSQL,PChar(fsql),@t);

if CompareText(DBType,'Oracle')=0 then
fsql := 'select S.TERMINAL from SYS.GV_$LOCKED_OBJECT L,ALL_OBJECTS O,SYS.GV_$SESSION S '
'where L.SESSION_ID=S.SID and S.AUDSID<>USERENV('#39'SESSIONID'#39') and '
'L.ORACLE_USERNAME=USER and O.OWNER=USER and O.OBJECT_ID=L.OBJECT_ID and '
'S.SID=L.SESSION_ID and O.OBJECT_NAME='#39 fTableName #39
else if (CompareText(DBType,'MSSQL')=0)or(CompareText(DBType,'SYBASE')=0) then
fsql := 'select p.hostname from master.dbo.syslocks l,master.dbo.sysprocesses p '
'where l.spid=p.spid and l.spid<>@@spid and object_name(l.id)='#39 fTableName #39
else raise Exception.CreateFmt('Unsupported DBMS %s.',[DBType]);

with TQuery.Create(nil) do begin
try
DataBaseName := DS.DatabaseName;
SQL.Text := fsql;
Open;
if not (Eof and Bof) then begin
if Trim(Fields[0].asstring)='' then fHostName:='Unknown'
else fHostName := Fields[0].asstring;
if (Integer(t)=0)or(r<>DBIERR_NONE) then begin
if not OldInTran then DS.Database.Rollback;
raise Exception.CreateFmt('鎖定資料失敗. 資料檔 %s 已被 %s 鎖定中.',[fTableName,fHostName]);
end;
Application.MessageBox(PChar(Format('資料檔 %s 可能已被 %s 鎖定.',[fTableName,fHostName])),'警告');
end;
finally
Free;
end;
end;
Result := True;
end;
OsX
版主


發表:6
回覆:151
積分:111
註冊:2003-05-03

發送簡訊給我
#7 引用回覆 回覆 發表時間:2008-09-15 10:10:06 IP:219.84.xxx.xxx 未訂閱
> select * from XXX with ( XLOCK, NOWAIT) where 1 = 1

> 此種方法已經試用過,不能得到想要的結果,還是會同時允許修改

此種方法已經用過, 不可以同時修改, 沒有問題

Delphi7 ADO MSSQL 2000 XP Client
agilehawk
一般會員


發表:3
回覆:10
積分:7
註冊:2008-09-05

發送簡訊給我
#8 引用回覆 回覆 發表時間:2008-09-16 08:58:42 IP:218.6.xxx.xxx 訂閱

===================引 用 OsX 文 章===================
> select * from XXX with ( XLOCK, NOWAIT) where 1 = 1

> 此種方法已經試用過,不能得到想要的結果,還是會同時允許修改

此種方法已經用過, 不可以同時修改, 沒有問題

Delphi7 ADO MSSQL 2000 XP Client

今日再次測試此種方法,確實能同時修改,只是只要有一個提交修改后,其他終端再提交保存修改時即會得到報錯信息“無法為更新定位行。一些值肯能已在最后一次讀取后已經更改。”
其實在任何數據庫中,用不用 with (xlock ,nowait) ,都能起到這樣的結果,所以以上語句在這種情況下,等同于 select * from XXX where 1=1

而我要的不是這個結果,我不能在用戶用去幾分鐘的時間編輯數據后,才給她提示不能保存,這樣要是我,我也會變成神經質的啦!
OsX
版主


發表:6
回覆:151
積分:111
註冊:2003-05-03

發送簡訊給我
#9 引用回覆 回覆 發表時間:2008-09-16 16:22:17 IP:220.128.xxx.xxx 未訂閱
我這邊確定可以,  我這邊都是寫在後端的 StoreProcedure 裏面,
既然你試不行, 要不要換一個參數試試 ?

select * from XXX with( XLOCK, READPAST ) Where xxx = yyy
agilehawk
一般會員


發表:3
回覆:10
積分:7
註冊:2008-09-05

發送簡訊給我
#10 引用回覆 回覆 發表時間:2008-09-16 17:15:28 IP:218.6.xxx.xxx 訂閱

===================引 用 OsX 文 章===================
我這邊確定可以, 我這邊都是寫在後端的 StoreProcedure 裏面,
既然你試不行, 要不要換一個參數試試 ?

select * from XXX with( XLOCK, READPAST ) Where xxx = yyy


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