• ベストアンサー

SQLServerの行ロック

VB6及びSQLServer2000で開発を行っているのですが 1つのテーブルに対して一度に複数の行ロックを 行う事が出来ずに困っています。 通常と違う方法が必要なのか、何か注意点があるのでしょうか? よろしくお願いします

質問者が選んだベストアンサー

  • ベストアンサー
回答No.4

単に、PKがIDだけではないとか、トランザクションをかけていないだけではないですか? 現在業務中のため、手元に環境がSQLサーバしかないので、 ・クエリアナライザ ・VBScript でやってみましたが、問題なしで普通にロックがかかりました。。。 私の行った方法が、そちらでもそのまま実現できるように、全て張っておきます。 ※1.テスト環境構築⇒pubs設定にしてあります ---------------------------------------------------------------------------------------------------------------- USE pubs GO if EXISTS(SELECT * FROM sysobjects WHERE id = OBJECT_ID(N'[TBL_NAME]') AND OBJECTPROPERTY(id, N'IsUserTable') = 1) DROP TABLE [TBL_NAME] GO CREATE TABLE [TBL_NAME] ( [ID] [numeric](8, 0) NOT NULL , [FLD] [char] (8) COLLATE Japanese_BIN NOT NULL CONSTRAINT [XPKTBL_NAME] PRIMARY KEY CLUSTERED ( [ID] ) ON [PRIMARY] ) GO INSERT INTO TBL_NAME VALUES(1,'A') INSERT INTO TBL_NAME VALUES(2,'B') INSERT INTO TBL_NAME VALUES(3,'C') INSERT INTO TBL_NAME VALUES(4,'D') INSERT INTO TBL_NAME VALUES(5,'E') GO SELECT * FROM TBL_NAME GO ---------------------------------------------------------------------------------------------------------------- ※2.ロック用のVBScript (必要に応じてGetConnection()関数を変更してください) ---------------------------------------------------------------------------------------------------------------- Option Explicit Call Main_Lock() 'メイン:ロック Sub Main_Lock() Dim adoCnn Dim adoRec Dim strSQL Set adoCnn = GetConnection() adoCnn.BeginTrans strSQL = "SELECT * FROM TBL_NAME with (rowlock,updlock) WHERE ID IN(2,3,4)" Set adoRec = adoCnn.Execute(strSQL) MsgBox adoRec.RecordCount & "件のデータをロック中...更新用のVBScriptを実行ください" adoCnn.CommitTrans 'またはRollbackTrans adoCnn.Close Set adoCnn = Nothing End Sub '汎用:コネクション Private Function GetConnection() CONST ADO_CUR_LOCATION_SERVER = 2 'ADODB.CursorLocationEnum.adUseServer CONST ADO_CUR_LOCATION_CILENT = 3 'ADODB.CursorLocationEnum.adUseClient Set GetConnection =CreateObject("ADODB.Connection") GetConnection.CursorLocation = ADO_CUR_LOCATION_CILENT GetConnection.Open "Provider=SQLOLEDB;" & _ "Data Source=(local);" & _ "Initial Catalog=pubs;", "sa", "sa" End Function ---------------------------------------------------------------------------------------------------------------- ※3.更新用のVBScript (必要に応じてGetConnection()関数を変更してください) ---------------------------------------------------------------------------------------------------------------- Option Explicit Call Main_Update() 'メイン:更新 Sub Main_Update() Dim adoCnn Dim strSQL Set adoCnn = GetConnection() strSQL = "UPDATE TBL_NAME SET FLD = 'わ' WHERE ID = 1" Call adoCnn.Execute(strSQL) Call Msgbox("STEP 1 終了") strSQL = "UPDATE TBL_NAME SET FLD = 'わ' WHERE ID = 4" Call adoCnn.Execute(strSQL) Call Msgbox("STEP 2 終了") strSQL = "UPDATE TBL_NAME SET FLD = 'わ' WHERE ID = 5" Call adoCnn.Execute(strSQL) Call Msgbox("STEP 3 終了") adoCnn.Close Set adoCnn = Nothing End Sub '汎用:コネクション Private Function GetConnection() CONST ADO_CUR_LOCATION_SERVER = 2 'ADODB.CursorLocationEnum.adUseServer CONST ADO_CUR_LOCATION_CILENT = 3 'ADODB.CursorLocationEnum.adUseClient Set GetConnection =CreateObject("ADODB.Connection") GetConnection.CursorLocation = ADO_CUR_LOCATION_CILENT GetConnection.Open "Provider=SQLOLEDB;" & _ "Data Source=(local);" & _ "Initial Catalog=pubs;", "sa", "sa" End Function

skyline33
質問者

お礼

返事が遅くなってすみませんでした。 おかげさまで、無事解決する事が出来ました。 ロック時のトランザクションのタイミングが悪かったようです。 ありがとうごさいました。

その他の回答 (3)

  • Senna_FF
  • ベストアンサー率45% (153/334)
回答No.3

SQL自体を見ると、なぜロックされないのか不思議ですね。 SQLServerの識者にも聞いてみたんですが、Primary以外にインデクスを張っていると、 まれにそんな現象が起きてたかもしれないみたいなことを言ってました。 さらに、トランザクションの分離レベルとかの問題もあるんじゃないのかともいってます。 (要はプログラマレベルの作業でなくSE作業だから現地環境見ないとわからないとのことなのです) ※お役にたてずすいません。Oracleなどと違ってSQLServerは資料も少なくて大変ですね。

skyline33
質問者

お礼

返事が遅くなってすみませんでした。 おかげさまで、無事解決する事が出来ました。 ロック時のトランザクションのタイミングが悪かったようです。 ありがとうごさいました。

  • Senna_FF
  • ベストアンサー率45% (153/334)
回答No.2

補足にかかれた内容で行ロックをかけるとして、どのようなSQLを組んでいますか? また、そのSQLでロックを書けた場合にロックがかからない状態とは、どのようなことを言うのでしょうか? (例:IDが2のみロック、3,4にかからない等)

skyline33
質問者

補足

先の表にたとえると select * from TBL_NAME with (rowlock,updlock) where ID in (2,3,4) といったSQLです 実際にロックが掛かるのは一行のみです(IDが2)

  • Senna_FF
  • ベストアンサー率45% (153/334)
回答No.1

>一度に複数の行ロック WHERE句に指定している行にロックをかけたいが、かからないということですか? まさか、PrimaryKeyは違うというおちではないですよね? 少し具体的に補足していただけますか?

skyline33
質問者

補足

ロックするの対象はPrimatyKeyです ID NAME 1 AAA 2 BBB 3 CCC 4 DDD といった表があった場合、IDが2,3,4の行を同時に ロックしたい場合のケースです

関連するQ&A