前提・実現したいこと
Access VBA からSQL Serverの[M_取引先マスタ]にテーブルロックを掛けて、フォームに入力があった内容を新規追加したく思っています。
発生している問題・エラーメッセージ
下記ロジックを実行すると、2つ目のSQL文実行時(M_取引先マスタのロックSQL)に
【実行時エラー '3705' オブジェクトが開いている場合は、操作は許可されません。】
とエラーになります。
SELECT COUNTのSQL文をコメントアウトすると、INSERT文の行で同エラーになります。
別ロジックで[DELETE]-->[INSERT]している部分では問題無く動作しているため、コピペするかたちで作ったのですが、SQL文実行の都度クローズしなくてはいけないのでしょうか?
該当のソースコード
Access
1 2Public CN_SQL As New ADODB.Connection 3Public RS_SQL As New ADODB.Recordset 4' ----------------------------------------------------------------------------- 5' Connectionオブジェクトを生成 6' ----------------------------------------------------------------------------- 7Public Sub DB_Connect() 8 9Dim ConnectionString As String 10 11Dim sDBSever As String 12Dim sDBName As String 13Dim sLoginID As String 14Dim sPassWD As String 15 16sDBSever = DLookup("[データ]", "M_システム", "[ID] = 'SvName'") ' SQL Serverが稼働しているサーバー名 17sDBName = DLookup("[データ]", "M_システム", "[ID] = 'DbName'") ' SQL ServerのDB名 18sLoginID = DLookup("[データ]", "M_システム", "[ID] = 'Login'") ' sa 19sPassWD = DLookup("[データ]", "M_システム", "[ID] = 'Pass'")' saのパスワード 20 21' 接続文字列 22ConnectionString = "Provider=SQLOLEDB;Data Source=" & sDBSever & _ 23 ";Initial Catalog=" & sDBName & _ 24 ";Connect Timeout=15" & _ 25 ";user id=" & sLoginID & _ 26 ";password=" & sPassWD 27 28' 接続 29CN_SQL.Open ConnectionString 30 31End Sub 32 33' ----------------------------------------------------------------------------- 34' データベースへの接続を解除する 35' ----------------------------------------------------------------------------- 36Public Sub DB_DISCONNECT() 37 38CN_SQL.Close 39Set CN_SQL = Nothing 40 41End Sub 42 43' ----------------------------------------------------------------------------- 44' 引数のSQL文を実行し、ADODB.Recordsetを返す 45' ----------------------------------------------------------------------------- 46Public Function DB_EXECUTE(s_SQL As String, CursorType, LockType, b_FLG As Boolean) As ADODB.Recordset 47 48b_FLG = True 49 50' タイムアウト設定 (15分) 51CN_SQL.CommandTimeout = 60 * 15 52 53' 処理された行数を示すメッセージが結果セットの一部として返されないようにする 54CN_SQL.execute ("SET NOCOUNT ON") 55 56' 警告メッセージが結果セットの一部として返されないようにする 57CN_SQL.execute ("SET ANSI_WARNINGS OFF") 58 59' オーバーフローおよび0除算時にはNULLを返す 60CN_SQL.execute ("SET ARITHABORT OFF") 61 62 63RS_SQL.CursorType = CursorType 64RS_SQL.LockType = LockType 65 66RS_SQL.Open s_SQL, CN_SQL 67'RS_SQL.Open s_SQL, CN_SQL, CursorType, LockType 68 69Do 70' レコードの操作ができるオブジェクト若しくは次のRecordSetがとれず、コネクションが空になった場合終了 71If RS_SQL.State = adStateOpen Or RS_SQL.ActiveConnection Is Nothing Then 72Exit Do 73End If 74Set RS_SQL = RS_SQL.NextRecordset() 75Loop 76 77Set DB_EXECUTE = RS_SQL 78 79 80' 設定OFF 81CN_SQL.execute ("SET NOCOUNT OFF") 82CN_SQL.execute ("SET ANSI_WARNINGS ON") 83CN_SQL.execute ("SET ARITHABORT ON") 84 85End Function 86 87' ----------------------------------------------------------------------------- 88' トランザクションを開始する 89' ----------------------------------------------------------------------------- 90Public Sub BeginTransaction() 91 92CN_SQL.BeginTrans 93 94End Sub 95 96' ----------------------------------------------------------------------------- 97' トランザクションをコミットする 98' ----------------------------------------------------------------------------- 99Public Sub CommitTransaction() 100 101CN_SQL.CommitTrans 102 103End Sub 104 105' ----------------------------------------------------------------------------- 106' トランザクションをロールバックする 107' ----------------------------------------------------------------------------- 108Public Sub RollbackTransaction() 109 110CN_SQL.RollbackTrans 111 112End Sub 113 114' ----------------------------------------------------------------------------- 115' F_取引先登録のコード 116' ----------------------------------------------------------------------------- 117'DB接続 118Call DB_CONNECT 119 120'SQL文生成 121s_SQL = "" 122s_SQL = "SELECT COUNT(*) AS REC_CNT " 123s_SQL = s_SQL & "FROM M_取引先マスタ " 124s_SQL = s_SQL & "WHERE 取引先CD LIKE '201804%';" 125 126i_Seq = REC_CNT + 1 127 128'SQL文実行 129RS_SQL.Open s_SQL, CN_SQL, adOpenStatic, adLockReadOnly 130 131'トランザクション開始 132Call BEGINTRANSACTION 133 134'SQL文生成 135s_SQL = "" 136s_SQL = "SELECT * FROM M_取引先マスタ WITH (TABLOCK, HOLDLOCK);" 137 138'SQL文実行 139'RS_SQL.Open s_SQL, CN_SQL, adOpenKeyset, adLockPessimistic 140 141s_SQL = "" 142s_SQL = "INSERT INTO M_取引先マスタ (取引先CD, 取引先名, 取引先住所, 更新日時) " 143s_SQL = s_SQL & "VALUES ( " 144s_SQL = s_SQL & "'" & s_SysDate & String(3 - Len(CStr(i_Seq)), "0") & CStr(i_Seq) & "', " 145s_SQL = s_SQL & "N'" & Forms!F_取引先登録.txt_取引先名.Value & "', " 146s_SQL = s_SQL & "N'" & Forms!F_取引先登録.txt_取引先住所.Value & "', " 147s_SQL = s_SQL & "'" & Format(Now(), "yyyy/mm/dd hh:mm:ss") & "' " 148s_SQL = s_SQL & ");" 149 150'SQL文実行 151RS_SQL.Open s_SQL, CN_SQL, adOpenKeyset, adLockPessimistic 152 153'SQL文コミット 154Call COMMITTRANSACTION 155 156'接続を閉じる 157Call DB_DISCONNECT 158 159 160 161' ----------------------------------------------------------------------------- 162' 以下は[DELETE]-->[INSERT]しているロジックです 163' ----------------------------------------------------------------------------- 164 165'----- DB接続 ----- 166Call DB_Connect 167 168'----- トランザクション開始 ----- 169Call BeginTransaction 170 171'該当データをDELETE --> INSERT 172s_SQL = "DELETE FROM T_案件テーブル WHERE ID = '" & KEY & "';" 173 174'SQL文実行 175RS_SQL.Open s_SQL, CN_SQL, adOpenKeyset, adLockPessimistic 176 177s_SQL = "INSERT INTO T_案件テーブル (ID, FLD1, FLD2, FLD3) " 178s_SQL = s_SQL & "VALUES ( , , , );" 179 180'SQL文実行 181RS_SQL.Open s_SQL, CN_SQL, adOpenKeyset, adLockPessimistic 182 183'----- DBコミット ----- 184Call CommitTransaction 185 186'----- 接続を閉じる ----- 187Call DB_DISCONNECT 188
試したこと
補足情報(FW/ツールのバージョンなど)
Access2010
SQL Server2014
回答1件
あなたの回答
tips
プレビュー