
Access2003での排他制御
顧客管理をAccess2003で行っています。
新規で登録するときに顧客IDの重複チェックを[顧客ID_LostFocus]内で
DCountを使って行っています。
[cmd登録_Click]で
Set db = CurrentDb
Set rst = db.OpenRecordset("顧客情報")
With rst
.AddNew
![顧客id] = me.txt顧客ID.value
![顧客住所] = me.txt顧客住所.value
![顧客TEL] = me.txt顧客TEL.value
・
・
・
.Update
End With
以上の処理を行っています。
(1)Aさんが新規登録で顧客IDを入力
(2)重複されていないので顧客名や住所の入力をおこなう。
(3)Bさんが同じ顧客IDで新規登録
このケースの場合、
Aさんはまだ登録処理が済んでいない(登録ボタンを押していないためテーブルに反映されていない)
ので(3)ではBさんの顧客IDは重複されていません。
Aさんが入力中の顧客IDをBさんが入力した時に「他のユーザーが使用しています」みたいな
メッセージを表示するにはどのようにしたらよろしいでしょうか??
文章が上手く書けなくてもうしわけありません、
何卒宜しくお願いいたします。
No.3ベストアンサー
- 回答日時:
直接的な回答にならないと思います(バフッとした感じで)
テーブル「T2」に、「番号」「名前」「登録日」があったとして、
長整数の「番号」を、新規登録のたびに+1していく例になります。
(エラー処理等、はしょっています)
(Updateでのみエラーが発生するものとして記述しています)
(番号の重複のみが引っかかる場合になります)
「番号」には重複なしのインデックスが設定されているものとします。
新規登録時、操作が競合しないように、「番号」を -999999 で一度登録します。
重複のエラーになったら時間をおいてリトライします。
登録成功で、「番号」最大値+1を覚えておいて、-999999 を書き換えます。
(登録成功で新規登録を抑止できるので、チェックをしたいのであればこのタイミングで)
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Function AddRec() As Boolean
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim iPhase As Integer
Dim sSql(1) As String
Dim iErrCnt As Integer
Dim bErrFound As Boolean
Dim iTmp As Long
Const iNumFix As Long = -999999
Const iRetryCount As Integer = 3
Set db = CurrentDb
sSql(0) = "SELECT TOP 1 * FROM T2 ORDER BY 番号 DESC;"
sSql(1) = "SELECT * FROM T2 WHERE 番号 = " & iNumFix & ";"
On Error GoTo ERR_HND
iErrCnt = 0
iPhase = 0
Do While (iErrCnt < iRetryCount)
bErrFound = False
Set rs = db.OpenRecordset(sSql(iPhase))
Select Case iPhase
Case 0
rs.AddNew
rs("番号") = iNumFix
rs("名前") = "AAAABCD"
rs("登録日") = Date
rs.Update
If (Not bErrFound) Then
rs.Requery
If (rs("番号") = iNumFix) Then
iTmp = 1
Else
iTmp = rs("番号") + 1
End If
iErrCnt = 0
End If
Case 1
rs.Edit
rs("番号") = iTmp
rs.Update
End Select
rs.Close
Set rs = Nothing
If (bErrFound) Then
Sleep 100
Else
iPhase = iPhase + 1
If (iPhase > 1) Then Exit Do
End If
Loop
Set db = Nothing
AddRec = iErrCnt < iRetryCount
Exit Function
ERR_HND:
rs.CancelUpdate
iErrCnt = iErrCnt + 1
bErrFound = True
iTmp = iTmp + 1
Resume Next
End Function
フォームから設定値を持って来る、
登録に成功した値をフォームに戻す等は、応用の範囲と思います。
「番号」-999999 が(エラーやトラブルで)残ったままへの処理は、
別途 -999999 を削除するものを作成するとか
レコードに登録した日時フィールドを追加して時間差を見て削除する処理を盛り込むとか・・・
(この場合は各PCの時刻合わせが必要と思います)
「番号」を採番する規則がなければ、この方法では?
この回答への補足
ご丁寧な回答ありがとうございます。
顧客IDは規則性はないです。
このロジックなら上手くいきそうです!
そもそも今の自分の作り方が正しいのかよくわかりません・・・。

No.4
- 回答日時:
No2です。
エラー処理ですが、AddNewの前にOn Error GoToを使用してエラー時にエラー処理ルーチンに飛ばしたらどうかということです。エラー処理ルーチン内ではErrオブジェクトを利用してエラーの種類を判別して対応するメッセージを表示するか、もしくはErr.Descriptionでエラーメッセージを表示されたらどうかということです。
これでエラーメッセージ終了後に画面に制御を戻すという感じです。
(結局、どこでチェックをしようと、チェック開始前から関連するテーブル全体をロックして他からの更新を排除して処理を行うようなことでもない限り、チェック後にAddNewが完了するまでの間に他から更新される可能性が否定できません。ですのでこのように実行時エラーに備えます。)

No.2
- 回答日時:
私としては仕様変更をお薦めします。
このプログラムはフォームのあるMDBとデータ(テーブル)のMDBを分離して作成し、非連結フォームで入力して更新時にテーブルに登録するタイプのプログラムではないかと想像しています。
この場合にAさん側で起動しているプログラムととBさん側で起動しているプログラムとでやりとりを行えるのはテーブルを介してしか手段がありません。
こうなりますと、Aさんが画面で入力中(まだ顧客情報テーブルには未登録)の顧客IDをBさん側で把握するためには、データのMDBに画面で入力中の顧客IDを一時保存するテーブルを作成し、Aさんが顧客IDを入力した際に(チェックが通った後に)その一時保存用テーブルに入力中の顧客IDを記録するような処理が必要になります。またこれに伴い少なくとも下記の処理が必要です。
・顧客IDのチェックは「顧客情報」テーブル+上記の一時保存用テーブルの両方に対して行う。
・画面で顧客IDを新しく入力した際には、一時保存用テーブルに顧客IDを登録する。
・画面で顧客IDを修正した際には、一時保存用テーブルに登録されている顧客IDも修正する。
・画面で更新したもしくは更新せず画面を終了した際には、一時保存用テーブルの顧客IDを削除する。
しかも、これだけやっても厳密に考えると一時保存用テーブルへの登録時に重複する可能性もありえるわけで・・・
こう考えますと、下記の仕様にした方がいいのではと思います。
・更新時にもう一度チェックを行う。(この場合LostFocusでのチェックは不要かもしれません)
・それでもタイミングが一致してテーブル登録時に重複する可能性があるので、AddNewする際にエラー処理を行う。(重複エラー時にその旨をメッセージ表示し、修正できるように画面に制御を戻す。)
この回答への補足
お丁寧な説明ありがとうございます。
>フォームのあるMDBとデータ(テーブル)のMDBを分離して作成し、
>非連結フォームで入力して更新時にテーブルに登録するタイプのプログラムではないかと
>想像しています。
その通りです。
LostFocusでは重複チェックは行わないで更新時にチェックを行うことにしまう。
>AddNewする際にエラー処理を行う
これは、
if CheckId(me.txt顧客ID.Value) = true then ←CheckId:Dcountを行っている関数
msgbox("顧客IDが重複しています")
else
rst.AddNew
・
・
・
endif
ということでしょうか??
No.1
- 回答日時:
たぶん以下の要件が必要になるのでしょうから、
これらの要件で検索をしてみてください。
(1)
排他制御とトランザクション処理を行なう。
(2)
その時のロックの競合を回避する。
(3)
ロックしたPCあるいはユーザーを確認、取得
例として
http://www.accessclub.jp/bbs3/0092/superbeg33086 …
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- その他(データベース) accessについて 2 2022/05/31 16:58
- Access(アクセス) Access IF文でテーブルに存在しない場合の処理について 2 2022/10/10 18:09
- 経営情報システム accessでの請求管理について 12 2022/06/11 16:20
- Visual Basic(VBA) Excel VBAのリストボックスの値を他のフォームに反映させる方法を教えてください。 2 2023/07/14 14:06
- Excel(エクセル) Excel 指定した固有番号で、複数の行を削除する方法は? 2 2022/03/30 15:18
- Excel(エクセル) 関数の式を教えてください 2 2022/04/04 11:15
- その他(開発・運用・管理) マイクロソフト製品のライセンス販売で困ってます 1 2022/06/30 19:52
- 営業・販売・サービス お客様先常駐のSEです。常駐しながら新規顧客の営業を行う方策などがあれば教えてください。 4月から新 3 2023/05/25 07:44
- その他(セキュリティ) fx口座開設し疑問があったのでfx業者のサポートの人にログインIDを教えてる所を間違ってログインパス 1 2022/03/24 17:33
- Visual Basic(VBA) 複数ページあるPDFファイル内の文字列等の情報をキーにPDFをグループ分け分割したい。 2 2022/06/25 09:51
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
ワードでの単純作業の効率化に...
-
Access フォームのデータがテー...
-
Access IF文でテーブルに存在し...
-
Access VBAでクエリーのレコー...
-
Accessにて検索結果の一覧表示...
-
データベースの1要素に複数デー...
-
Access クエリ このレコードセ...
-
Accessで移動累計
-
複数のフィールドから条件を抽出
-
別のDBからテーブルをコピーす...
-
Access2013VBA 複数のテーブル...
-
ワードで保存するファイル名の...
-
Access2003での排他制御
-
Excel 2019 のピボットテーブル...
-
「直需」の意味を教えてください
-
エクセルVBAで5行目からオート...
-
Accessでテーブル名やクエリ名...
-
Oracle 2つのDate型の値の差を...
-
INSERT INTO ステートメントに...
-
SQLServer2005のSQL文での別名...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
Access VBAでクエリーのレコー...
-
Access フォームのデータがテー...
-
データベースの1要素に複数デー...
-
Access IF文でテーブルに存在し...
-
ワードでの単純作業の効率化に...
-
Access 既に開いているフォー...
-
別のDBからテーブルをコピーす...
-
顧客IDを入力すると顧客名や住...
-
ACCESS で マクロの中でフィ...
-
ワードで保存するファイル名の...
-
Access 縦(行)のデータを横(列)...
-
シングルクォーテーションとダ...
-
ADOでレコードを閉じるタイミン...
-
Access レコードロックについて...
-
Accessデータベースで行と列を...
-
テーブル1 2 3 の結合
-
子フォームから別(孫)フォー...
-
Access2013VBA 複数のテーブル...
-
主キーやオートインクリメント...
-
Accessで名寄せグループの関係...
おすすめ情報