レコード単位にトランザクションかけられる?

このQ&Aのポイント
  • Access2003 Win-XP で、複数のPCで同じレコードを編集すると、待機中の状態になる現象が発生します。
  • ただし、最初にレコード編集中の人がいる場合は、別のPCの人が別のレコードを編集することができ、待機する必要はありません。
  • しかし、更新はされていないにも関わらず、更新されたかのように終了してしまいます。対策はあるのでしょうか?
回答を見る
  • ベストアンサー

レコード単位にトランザクションかけられる?

Access2003 Win-XP です。 下記コーディングで現象は・・・ ・2つのPCで同じレコードを編集すると、あとから編集する人は待機中になる。 ・しかしながら、同じテーブルで最初にレコード編集中の人がいたとき、別PCの人が別レコードを編集することは可能で待機することはない(これは正常)。そして正常に更新されたかのように終了する。しかしながら、更新はされていない。   (更新されないのにエラーハンドリングできない) これはいったいどういうことでしょうか? 何か対策はないでしょうか? Dim ret_value As Variant Dim wsp As Workspace Dim dbs As Database Dim rsA Set wsp = DBEngine.Workspaces(0) Set dbs = CurrentDb wsp.BeginTrans Set rsA = dbs.OpenRecordset("在籍表", dbOpenDynaset, dbSeeChanges, dbPessimistic) Do Until rsA.EOF If rsA.[出席番号] = Me.[出席番号] Then rsA.Edit rsA.[氏名] = Me.[氏名] rsA.Update rsA.MoveLast End If rsA.MoveNext Loop rsA.Close ret_value = MsgBox("Commit ?", vbYesNo) If ret_value = vbYes Then wsp.CommitTrans Me.Requery Else wsp.Rollback End If Exit_コマンド34_Click: Set wsp = Nothing Exit Sub Err_コマンド34_Click: MsgBox Err.Description Resume Exit_コマンド34_Click  

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

  • ベストアンサー
  • nda23
  • ベストアンサー率54% (777/1415)
回答No.3

エラーにならず、更新も反映されないとなると、 (1)BeginTrans~CommitTransが重複しないで実行された。 (2)DBエンジンのバグ (3)プログラム側の錯誤(エラーをスリ抜けさせてしまうなど) のどれかなんでしょうね。当方で同様の実験しましたが、エラーになりました。 環境は以下の通りです。 OS:XP-Professional SP3 Access:11.0(Jet:4.0、ADO:2.8、VBA:6.05)

onakichi
質問者

お礼

nda23さん、本当にありがとうございました。 また分からないことがありましたら、よろしくお願いします。

onakichi
質問者

補足

なにやら、いろいろ試しているうちに正常に動きました。 デバッグモードで止めたり、closeしなかったり、ワークスペースを開放せずに何度もテストを行ったりした影響かもしれません。 実際に他にも変な動きをした時に、一度mdbを終了させて再度実行すると正常に動く場合がよくありましたので。 今はず~っと正常に動いています。 おそらくそのへんの影響かと思われます。 nda23には、いろいろと調べていただき本当にありがとうございました。 そして、申し訳ありませんでした。

その他の回答 (2)

  • nda23
  • ベストアンサー率54% (777/1415)
回答No.2

繰り返しますが、トランザクションがカブっても、Edit~Updateの時期が 重複しなければエラーになりません。これは不思議なことではありません。 私の言う更新日時の制御とは画面表示用にDBから読み出した時に取得した レコードの更新日時と、更新のために作成したレコードセットから得られる 更新日時(最新の更新日時)を比較するこです。両者が異なるということは 「画面処理中に誰かが更新した=表示内用が古い」ということを意味します。 この場合、最新情報をDBから再取得して内容を確認するか、現行の更新を 強行するかを問い合わせるなどの処置を施します。

onakichi
質問者

補足

すみません。私の説明がへたなせいか質問の主旨が伝わっていないようです。 nda23さんの言われる更新日時の制御は別途行っておりますが、上記のコーディングでは省略しています。 問題は、レコード単位の制御が正常に行われないことです。 同じテーブルで同時に別レコードの編集を行っている人の更新が待機状態にもエラーにもならず終了したにも関わらず、実際のテーブルを見ると更新されていないことなのですが、 質問の主旨が分かっていただけたでしょうか? 何度も分かりづらい説明してしまって申し訳ありません。

  • nda23
  • ベストアンサー率54% (777/1415)
回答No.1

トランザクション管理とレコードの排他制御は別物で、目的も違います。 トランザクション管理とは一連の複数のテーブル/レコードを更新する場合、 部分的に成功、部分的に失敗ということが起き、テーブル/レコード間で、 矛盾が生じることを防ぐため、成功した更新も無かったこと(RollBack)にし、 全ての更新が成功した時、始めてその内容を反映(Commit)するという 制御です。掲題のように単一テーブルの単一レコードの更新の場合は あまり、意味がありません。 更新の排他制御は同時更新を防ぐもので、更新を開始してから完了する までの間、他の更新を排除するということです。掲題のオプションでは Edit~Updateの間だけロックされますが、期間がズレていれば複数の プロセスで同じレコードを更新してもエラーになりません。 私はこういう場合、ミューテックス代わりにファイルと、更新日時を使って 制御しています。

onakichi
質問者

補足

上記コーディングは、なるべく簡素化して現象だけを検証するために省略したものです。 更新日時による制御は元のコーディングでは行っております。 それでも上記現象が起こるのが不思議です。

関連するQ&A

  • Transactionで待機状態になりません

    Access2003 Win-XPです。 ネットワーク上にmdbを置いて、複数ユーザーで共用して使用していますが、マルチユーザー環境での制御が出来ません。 具体的には、ある人(Aさん)がBeginTransからCommitする間に別の人(Bさん)が同じデータを更新しようとしてBeginTransをスルーしてしまいます。 待機状態になりません。 (いわゆるLockの概念とは違うのでしょうか?) 確かに、Bさんの更新はテーブルへ反映されることはないのですが、何もなかったようにスルーして処理が進んでしまいます。 エラーにもならないのでハンドリングしようがないです。 これでは、Bさんはあたかも自分の更新が成功したかのように錯覚をしてしまいます。 分厚い壁にぶち当たり、何をどうしたらよいのかまったくわかりません。 どなたかご教授ください。 具体的なコーディングは下記です。 Dim ret_value As Variant Dim wsp As Workspace Dim dbs As Database Set wsp = DBEngine.Workspaces(0) Set dbs = CurrentDb wsp.BeginTrans  dbs.Execute "update [tm_memory_card] set [機種] = '" & Me.[機    種] & "'" dbs.Close ret_value = MsgBox("Commit ?", vbYesNo) If ret_value = vbYes Then wsp.CommitTrans Me.Requery Else wsp.Rollback End If テストしやすいように、Commit直前で処理を止められるようにしました。

  • Access2007 サブフォームのレコードを一括印刷する方法

    お世話になっております。 サブフォームは帳票型になっており、下記で表示されている全レコードのチェックが入ります。 これと平行して、各レコードを印刷したいのですが、カーソルがあるレコードのみがレコードの数だけ印刷されてしまいます。 これを各レコードごとに印刷したいと思います。 Dim dbs As Database Dim rst As Recordset Dim strSQL As String Set dbs = CurrentDb Set rst = Me.RecordsetClone With rst If .RecordCount > 0 Then .MoveFirst Do Until .EOF .Edit !チェック = True DoCmd.OpenReport "印刷", acNormal, , "コード=" & Me.コード .Update .MoveNext Loop End If .Close End With ご教授いただければ幸いです。よろしくお願いいたします。

  • サブフォームのレコード削除

    サブフォーム(帳票)のレコード削除をしたいのですが、レコードセクレタをクリックして選んだレコードではなく、テーブルの最初のレコードから順番に削除されてしまいます。 Dim cn As ADODB.Connection Dim rs As ADODB.Recordset Dim ret As Integer '接続 Set cn = CurrentProject.Connection 'レコードセットを取得 Set rs = New ADODB.Recordset rs.Open "T支店", cn, adOpenKeyset, adLockOptimistic '削除 ret = MsgBox("表示中のレコードを削除しますか?", vbYesNo + vbQuestion, "削除") Select Case ret Case vbYes rs.Delete Me!sub支店.Form.Requery Case vbNo Exit Sub End Select '終了 rs.Close: Set rs = Nothing cn.Close: Set cn = Nothing WINDOWS98、ACCESS2000をしようしています。よろしくお願いします。

  • 非連結フォームにレコード表示したい!

    フォームにレコードを表示させたいのですが、 ”FROM 句の構文エラー”と出ます、ヘルプを参照すると何故か表示されません! 「strSQL~Me!年号コード」までの間が間違っているのでしょうか? アドバイス宜しくお願いいたします。 Dim adoCON As ADODB.Connectio Dim adoREC As ADODB.Recordset Dim strSQL As String Set adoCON = Application.CurrentProject.Connection strSQL = "SELECT *" _ & "FROM ta01年号" _ & "WHERE 年号コード =" & Me!txt年号コード Set adoREC = adoCON.Execute(strSQL) If adoREC.EOF = False Then Me!txt年号コード.Value = adoREC(年号コード).Value Me!txt年号.Value = adoREC("年号").Value Else MsgBox "該当データがありません", vbOKOnly + vbExclamation, "年号" Cancel = True Exit Sub adoREC.Close adoCON.Close Set adoREC = Nothing Set adoCON = Nothing End If

  • アクセスのフォームからレコード入力空欄回避のVBA

    アクセス初心者です。 帳票式フォームからテーブルへのレコード入力において、次のレコード入力ボタンで空欄を防止するためのVBAを作っていますが、うまく行きません。空欄があれば警告は出ますがそのままテーブルへ記録されてしまいます。 テーブルに記録されずに空欄が入力できるようにするにはどうすればよいのでしょうか? また、次を入力するときにフォームの製品名の内容だけ消えずに残したいのですが、そのプログラムについても教えていただきたいです。 なかなかうまく行かずに大変困っています。 どなたかVBAの達人の方、初心者にわかりやすくお教え下さい。 「入力内容を登録して次を入力」ボタンで作ったVBAは次の通りです。 つぎはぎなので、不要なプログラムもあるかもしれません。 Private Sub コマンド9次のレコードに_Click() On Error GoTo Err_コマンド9次のレコードに_Click DoCmd.GoToRecord , , acNext Exit_コマンド9次のレコードに_Click: Exit Sub Dim Rst As DAO.Recordset Set Rst = CurrentDb.OpenRecordset("T_指定材料表", dbOpenTable) With Rst .AddNew .Fields("製品名") = Me!製品名 .Fields("回路記号") = Me!回路記号 .Fields("部品名") = Me!部品名 .Fields("員数") = Me!員数 .Update If IsNull(Me!製品名) Then MsgBox ("製品名が空欄です。") Resume Exit_コマンド9次のレコードに_Click End If If IsNull(Me!回路記号) Then MsgBox ("回路記号が空欄です。") Resume Exit_コマンド9次のレコードに_Click End If If IsNull(Me!部品名) Then MsgBox ("部品名が空欄です。") Resume Exit_コマンド9次のレコードに_Click End If If IsNull(Me!員数) Then MsgBox ("員数が空欄です。") Resume Exit_コマンド9次のレコードに_Click End If End With On Error Resume Next DoCmd.GoToRecord DataForm, "T_指定材料表", acNew Rst.Close Set Rst = Nothing Call ClearControls End Sub

  • Access カレントレコードがありません

    フォーム社員情報からレコードを削除するボタンを作成してレコードの削除を行いたいのですが、全て削除をして1件もなくなった場合にデータベースを閉じる時に「カレントレコードがありません」というエラーが出てしまいます。OKをクリックすると閉じる事は閉じれるのでこのエラーが出ないようにしたいのですが。。。 よろしくお願いします。 'エラー開始 On Error GoTo err_RTN: '接続 Set cnADO = CurrentProject.Connection 'レコードセットを取得 Set rsADO = New ADODB.Recordset rsADO.Open "T社員情報", cnADO, adOpenKeyset, adLockOptimistic '削除 ret = MsgBox(Me!txt氏名.Value & Chr(13) & "を削除しますか?", vbYesNo + vbQuestion, "削除") Select Case ret Case vbYes rsADO.Delete Me.Requery Case vbNo Exit Sub End Select '終了 rsADO.Close: Set rsADO = Nothing cnADO.Close: Set cnADO = Nothing

  • アクセスのVBAでテキストデータのリンクを更新したいのですが

    コードは以下ですが、リンクの更新がうまくいかず更新されずに終了 してしまいます。 Function RefreshLinks(strFileName As String) As Boolean '指定されたデータベースへのリンクを更新します。更新に成功した場合は、True を返します。 Dim dbs As Database Dim intCount As Integer Dim tdf As TableDef 'データベースの全てのテーブルをループします。 Set dbs = CurrentDb For intCount = 0 To dbs.TableDefs.Count - 1 Set tdf = dbs.TableDefs(intCount) 'tdf.connectがある場合、それはリンクテーブルです。 If Len(tdf.Connect) > 0 Then tdf.Connect = "text;databese=" & strFileName Err = 0 On Error Resume Next tdf.RefreshLink 'テーブルのリンクを更新します。 If Err <> 0 Then RefreshLinks = False Exit Function End If End If Next intCount RefreshLinks = True 'リンクの更新が完了しました。 End Function

  • accessについて<BOFとEOFのいずれかがTUREになっているか・・・現在のレコードが必要です>

    Private Sub kensaku_Click() On Error GoTo Err_kensaku_Click Screen.PreviousControl.SetFocus Dim ss As String Dim rs As String Dim strSQL As String Dim rstType As ADODB.Recordset Set rstType = New ADODB.Recordset ss = text.text strSQL = "Select 見積日 From 見積 where 提出見積No ='" & ss & "'" rstType.Open strSQL, CurrentProject.Connection, adOpenKeyset, adLockOptimistic, adCmdText If ss = "" Then MsgBox ("提出見積Noを入力してください") ElseIf rstType.EOF = False Then While rstType.EOF = False rs = rstType.GetString MsgBox (rs) rstType.MoveNext Wend kikaiNo.Value = "222" Else MsgBox ("提出見積Noが存在しません") End If Exit_kensaku_Click: Exit Sub Err_kensaku_Click: MsgBox Err.Description Resume Exit_kensaku_Click End Sub 以上は書いた検索のコードですが、<BOFとEOFのいずれかがTUREになっているか、または現在のレコードが削除されています。要求された操作には、現在のレコードが必要です>というエラーが出てきます。問題がどうかよくわかりませんので、教えていただけませんか。

  • ACCESS/VBA 追加レコードが表示されない

    ACCESS 2003 で開発しています。 フォームのデータソースがテーブルAで、テーブルAの主キーはオートナンバーです。 フォーム上のボタンをクリックすると、追加クエリを実行して、テーブルAに1レコード追加し、 フォームにそのレコードを表示したいのですが、 クエリ実行前の最終レコードが表示されてしまいます。 テーブルAを見ると、オートナンバーがふられたレコードが末尾にちゃんと追加されています。 Dim dbs As Database Dim Qdf As QueryDef Set dbs = CurrentDb Set Qdf = dbs.QueryDefs("Q_データ追加2") ←追加クエリ Qdf.Execute Me.Refresh '* 最終レコードを表示 DoCmd.GoToRecord , , acLast どのようにすれば、直前に追加したレコードをフォームに表示できるのか おわかりの方がおられましたら、お教え下さい。ちなみに、ACCESSは、   「既定の開くモード 」:共有モード   「既定のレコードロック」:ロックしない      という設定になっています。 よろしくお願い致します。

  • Accessでレコードの複製

    Access2010を使用して入力フォームを作成しています。 メインフォームとサブフォームにそれぞれ顧客情報を表示させていて、 「複製」ボタンを押すと、 メインフォーム、サブフォームのレコードがコピーされるようにしています。 メインフォームの元テーブルはJIK サブフォームの元テーブルはREN です。 JIKおよびRENテーブルはほかからリンクさせているのですが、 これで「複製」ボタンを押すと、 "実行時エラー '3022': インデックス、主キー、またはリレーションシップで重複する値が生成されるためテーブルに要求した変更でした成功しました。フィールドまたは重複データが含まれている、インデックスを削除するフィールド内のデータを変更または重複するエントリを許可して、やり直してのインデックスを再定義します。このエラーは、レポートやレポートの生成に変更を保存するときに発生します。 が出てしまいます。 テーブルをインポートすると正常に動作します。 テーブルをリンクさせる場合、レコードの複製は不可能なのでしょうか? VBAは以下のように記述してみました。 Private Sub コマンド10_Click() On Error GoTo Err_コマンド10_Click Dim Result As Integer Result = MsgBox("このデータを複製しますか?", vbYesNo + vbDefaultButton2 + vbQuestion, "データの複製確認") If Result = vbYes Then Me!txtCopy事件ID = Me!事件ID Dim stDocName As String DoCmd.RunCommand acCmdSelectRecord 'カレントレコードの選択 DoCmd.RunCommand acCmdCopy '選択レコードのコピー DoCmd.GoToRecord , , acNewRec '新規レコードに移動 DoEvents ' (必要に応じて) DoCmd.RunCommand acCmdPasteAppend 'コピーレコードの追加貼り付け DoCmd.SetWarnings False ' システムメッセージ非表示 stDocName = "追加クエリ" DoCmd.OpenQuery stDocName, acNormal, acEdit DoCmd.SetWarnings True ' システムメッセージ表示 ' サブフォーム再クエリ Me!SREN.Requery ' 追加したレコードに移動 DoCmd.GoToRecord , , acLast Me.リスト31.Value = Me.リスト31.ItemData(0) MsgBox ("データを複製しました") Exit_コマンド10_Click: Exit Sub Err_コマンド10_Click: MsgBox Err.Description Resume Exit_コマンド10_Click Else MsgBox "データの複製をキャンセルしました" End If End Sub 追加クエリは以下のように作成してみました。 【追加クエリ】 INSERT INTO REN ( 事件ID, 氏名, フリガナ, ・・・ ) SELECT [Forms]![MAIN]![事件ID] AS 式1, REN.氏名, REN.[フリガナ], REN.報告書, ・・・ FROM REN WHERE (((REN.事件ID)=[Forms]![MAIN]![txtCopy事件ID]));