Access2000 VBA(ADO)を使用して主キーの空きを探す方法

このQ&Aのポイント
  • Access2000 VBA(ADO)を使用して、主キーの空きを探す処理を作成しましたが、うまくいきません。
  • テーブルの主キーには「KEY-0」から「KEY-10」までの値が入力されており、空きの主キーを探したいです。
  • 処理を実行すると、「KEY-10」で処理が抜けてしまいますが、期待するのは「KEY-11」の空きです。ご教授お願いします。
回答を見る
  • ベストアンサー

Access2000 VBA(ADO)を使用して主キーの空きを探す処理

「id」(文字型・8バイト)を主キーとした、簡単なテーブルを作成しました。 この「id」のフィールドには一応「KEY-0」~「KEY-10」まで入力されています。 (数字の部分は0,1,2,3,4,5・・・10となっています。) この主キーの空き(重複しない値)を探す処理を以下の様に作成しましたが、どうも上手いきません。 期待する主キーの空きは、「KEY-11」だと思うのですが、なぜか「KEY-10」で処理が抜けてしまいます。 ソフトウェア)Access2000 言語)VBA(ADOを使用しました。) 初歩的な事かもしれませんが、とても悩んでいます。 どなたかご教授いただけないでしょうか? 何卒、宜しくお願いします。 処理ここから Private Sub IdCheck_Click() Dim cn As ADODB.Connection Dim rs As ADODB.Recordset Dim i As Integer Dim TempKey as String Dim flgKey As Boolean Set cn = CurrentProject.Connection Set rs = New ADODB.Recordset rs.Open "TEST_TABLE", cn, adOpenKeyset, adLockOptimistic '各変数など初期化 TempKey = "" i = 0 flgKey = False '主キーの空きを探すまで処理を繰り返す。 Do TempKey = "KEY-" & CStr(i) rs.Find "id='" & TempKey & "'" '主キーの空きがあった場合 If rs.EOF Then '処理を終える flgKey = True '主キーの空きがない場合 Else i = i + 1 End If Loop Until flgKey = True '一応表示させて値の確認をしています。 MsgBox TempKey rs.Close Set rs = Nothing cn.Close Set cn = Nothing End Sub ここまで

  • jone
  • お礼率94% (18/19)

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

  • ベストアンサー
noname#182251
noname#182251
回答No.2

失礼なことを伺うようで恐縮ですが(^^; ご提示のような方法で空きキーを探すのに特別な理由があるのでしょうか? データベースを使うメリットが全くないように思われます。折角の主キーなのにデータ多数でも最初から1件ずつ比較して探して行く気の遠くなるような処理です。 単に重複しないキーということであれば「オートナンバー型」が一番簡単です。 データ入力が取り消された時、番号が飛んでしまうことを嫌うのであれば SELECT Max(xx.ID) AS IDの最大 FROM xx; みたいなSQL文で求めた最大値に+1するとか 上記例ですとどちらも数値型ですが、主キーが文字型であることにも理由があるのでしょうか? 必ず「KEY-」が付いているのも冗長に感じられます。 それぞれに理由があると思いますが、それを明示されれば、より適切なレスが付くと考えます。

jone
質問者

お礼

早速、ご教授くださいまして有難うございます。 また、お返事遅くなり申し訳ございませんでした。 fuuten_no_neko様のご指摘が、とても的確なご回答だと感じました。 >データベースを使うメリットが全くない 「あぁ、そうか。やっぱり甘いなぁ、自分は・・・」と思わず溜息をついてしましました。。。 おっしゃるとおりですね。 根本的にDBやSQLの勉強不足と痛感いたしました。 >主キーが文字型であることにも理由があるのでしょうか? 文字型である理由は特にありませんでした。 プログラムベースで主キーを割り当てようと考えた時、「折角なら、それからどんな番号、コードなのか分かった方が良いのかな?」なんて考えたものですから。 当初、主キーはオートナンバー型で考えていました。 ただ、参考書やWeb等で調べてみたところ、いくつかオートナンバー型の使用に注意・否定的な意見が見受けられましたので使用すべきではないのかと思い・・・ 「プログラムで制御」→「主キーを文字型」→「主キーの空きを探す処理(プログラム)」の様に考えが移行していってしまった訳です。。。 でも、オートナンバー型や文字型にせよ、要は使いどころなんでしょうか。 fuuten_no_neko様のご教授いただいたとおり、主キーを数値型にして、SQLまたはオートナンバー型で考え直したいと思います。 >失礼なことを伺うようで恐縮ですが とんでもございません!! まだ、この様な場での質問に不慣れなものでして。 スミマセン。 >それを明示されれば、より適切なレスが付くと考えます。 おしゃるとおりですね。 今後、出来る限り簡潔・的確にお伝えする様努めます。 また、煮詰まってしまった場合こちらで、教えを請う事が多々あるかと思いますが、宜しくお願いいたします。 本当に有難うございました。

その他の回答 (1)

回答No.1

ADOのFINDメソッドは、パラメータ省略時カレント行より後ろをサーチしますが... そのロジックで、KEY-1 KEY-2 KEY-3 ・・・ KEY-10 の順で行が存在することが、 保証されていますか? ということを考えて見てください。 というか、最も合理的な処理は、”空き番”自体を問い合わせるSQLを使うことだと思います。 それにより、VBAでの無駄なロジックを消化できるかと思います。

jone
質問者

お礼

早速、ご教授くださいまして有難うございます。 また、お返事遅くなり申し訳ございませんでした。 >ADOのFINDメソッドは、パラメータ省略時カレント行より後ろをサーチしますが... >KEY-1 KEY-2 KEY-3 ・・・ KEY-10 の順で行が存在することが、保証されていますか? いや、全く保証されていませんでした。 ADOのDB操作に関してもう少し調べたいと思います。 同時にfuuten_no_neko様に述べた内容と重なってしまいますが、DBやSQLの勉強をもっとしようと思います。 今回は、SQLまたはオートナンバー型で考え直したいと思います。 また、煮詰まってしまった場合こちらで、教えを請う事が多々あるかと思いますが、宜しくお願いします。 本当に有難うございました。

関連するQ&A

  • 【ACCESS2000】 VBAの更新処理に条件を加えたい。

    下記のような更新処理のVBAを組みました。 これにIDが5のものを更新するというのを加えるには どうすればよいでしょうか。 Dim cn As ADODB.Connection Dim rs As New ADODB.Recordset Set cn = CurrentProject.Connection rs.Open "tbl_D_売上", cn, adOpenKeyset, adLockOptimistic, adCmdTableDirect rs("入金方法") = 2 rs("入金方法名称") = "分割" rs.Update rs.Close Set rs = Nothing cn.Close Set cn = Nothing

  • Access ADOについて質問です。

    Access ADOについて質問です。 以下コードでレコードセットを返す関数を使用しています。 動作的には問題ないのですが、標準モジュール内のレコードセットをClose及びNothingしていないのが気になります。 Private Sub Form_Open(Cancel As Integer) Dim rs2 As ADODB.Recordset Set rs2 = New ADODB.Recordset Set rs2 = CreateRecordSet("SELECT * FROM T_Standard;") Set Me.Recordset = rs2 rs2.Close: Set rs2 = Nothing end sub '標準モジュール Public Function CreateRecordSet(strSQL As String) As ADODB.Recordset Dim cn As ADODB.Connection Dim rs As ADODB.Recordset Set cn = New ADODB.Connection cn.ConnectionString = "provider=Microsoft.Jet.OLEDB.4.0;" _ & "Data Source=O:\標準DB\StandardBackEnd.mdb" cn.Open Set rs = New ADODB.Recordset rs.Open strSQL, cn, adOpenStatic, adLockReadOnly Set CreateRecordSet = rs ' rs.Close: Set rs = Nothing   ←この部分 ' cn.Close: Set cn = Nothing   ←この部分 End Function 標準モジュール内ではCloseやNothingしなくてもメモリの開放は行われているのでしょうか? アドバイスよろしくお願いいたします。

  • アクセスVBA。ADO

    CSVから列を分割してテーブルにしたいかったので 下記のコードを記述しましたが、 Dim cn As ADODB.Connection Dim rs As New ADODB.Recordset Dim datacount As Long Set cn = New ADODB.Connection With cn .ConnectionString = "Provider=Microsoft.jet.OLEDB.4.0;Data Source=" & CurrentProject.Path & "\;" .Properties("Extended Properties").Value = "text;HDR=YES;" .Open End With Set rs = cn.Execute("SELECT * FROM 構成マスタ.csv") datacount = rs.Fields.Count For i = 0 To datacount strsql = "SELECT " & rs.Fields(i).Name & " INTO " & rs.Fields(i).Name & " FROM 構成マスタ.csv;" cn.Execute strsql Next i rs.Close cn.Close Set rs = Nothing Set cn = Nothing SQLを実行するところで、「日付エラー」となってしまいます。 データには特に日付等はないのでエラーになる原因がわかりません。 どなたかご教示いただけますでしょうか。

  • ACCESS VBA

    ACCESSで検索フォームを作りたいと思っています。 VBAを使って行きたいと思うのですが、うまくいきません。 希望としては、該当するレコードのデータを抽出したいです。 よろしくお願いいたします。 ※現段階でのソースを書いてみました。 最終的に行いたい処理とは違うのですが、根本的に間違っているようなので簡略化しました。 /------------------------------------------------/ Private Sub コマンド1_Click() Dim cn As ADODB.Connection Dim rs As ADODB.Recordset Dim sql As String '接続 Set cn = CurrentProject.Connection 'レコードセットを取得 Set rs = New ADODB.Recordset sql = "SELECT * FROM 従業員データ " & _ "WHERE 年齢=30" rs.Open sql, cn, adOpenDynamic, adLockReadOnly rs.Close: Set rs = Nothing cn.Close: Set cn = Nothing End Sub /------------------------------------------------/

  • VBA ADOのフィルタのアポストロフィーの意味は

    VBAで文字列はダブルコーテーション「”」で括りますが ------------------------------------------------ Sub ADO_Filter() Dim cn As ADODB.Connection Dim rs As ADODB.Recordset Set cn = CurrentProject.Connection Set rs = New ADODB.Recordset rs.Open "T社員名簿", cn, adOpenKeyset, adLockOptimistic rs.Filter = "質問タイトル LIKE '*田*'" rs.Close: Set rs = Nothing cn.Close: Set cn = Nothing End Sub ------------------------------------------------ 上記の '*田*' のアポストロフィーはどういう時に必要なのでしょうか? LIKE演算子を使ってるからか Filterだからか など理由があれば教えて下さい。 また、「'」を使っているのに、以後がコメントにならないのも不思議です。 よろしくお願い致します。

  • VB6.0 の主キーの上書き処理について

    いつもお世話になっております。 VisualBasic6.0の勉強をしています。 Text1、Text2、Commmand1 を配置したフォームを作成し、 Text1に番号、Text2に名前、を入力後、 Command1ボタンを押すと、 MySQLサーバにデータが登録される処理を作成しているのですが、 下記のプログラムでは登録は出来るのですが、 サーバ側で、主キーはText1で入力した番号にしているため、 サーバ側で登録済みの番号を入力し登録処理を行った際、 『実行時エラー'2147467259 プライマリー重複のエラーメッセージ』 が表示されます。 主キーを上書きする際は、どのような処理を加えればよいのでしょうか? Private Sub Command1_Click()  Dim cn As ADODB.Connection  Dim rs As ADODB.Recordset   Set cn = New ADODB.Connection   Set rs = New ADODB.Recordset  Dim strTBL As Variant   strTBL = "test" 'テーブル名   'Mysqlへ接続   cn.Open "Driver={MySQL ODBC 3.51 Driver};~略~   'テーブルを開く   rs.Open strTBL, cn, adOpenForwardOnly, adLockOptimistic, adCmdTable rs.AddNew       '新規レコードを追加   rs!no = Text1.Text           'ナンバーをセット   rs!Name = Text2.Text          '名前をセット  rs.Update       '更新(保存)  rs!no = Text1.Text           'ナンバーをセット  rs!Name = Text2.Text          '名前をセット  cn.Close  Set cn = Nothing  Set rs = Nothing  MsgBox "登録完了", vbOKOnly, "登録"     Text1.Text = ""            '登録後、テキストの内容を消去  Text2.Text = "" End Sub ご教示、よろしくお願いいたします

  • ADOでレコードを閉じるタイミング。。Access2000/VB6/Win2K

    レコードセットを返すFuncitonプロシージャーを作ってみたのですが。。。 下のGet_Recordsの方のレコードセットをCloseすると上の方のDisp_Dataでオブ ジェクトが閉じているといって怒られます。しかし、閉じないと下の方では開きっ ぱなしになると思うのですが。。。どのように処理すればいいのでしょうか? Public P_CN As ADODB.Connection Private Sub Disp_Date()   Dim RS As ADODB.Recordset   Dim SQL AS String    Set RS = Get_Records(SQL)     With RS      If .RecordCount > 0 Then       .MoveLast: .MoveFirst       .Debug.Print !顧客_ID        End If      End With      RS.Close     Set RS = Nothing End Sub Public Function Get_Records(pSQL As String) As ADODB.Recordset   Dim RS As ADODB.Recordset     Set RS = New ADODB.Recordset      RS.Open pSQL, P_CN, adOpenKeyset, adLockOptimistic     Set Get_Records = RS '''    RS.Close '''   Set RS = Nothing End Function

  • Accessでのデータベースの使用(VBA)

    Private Sub 実行_Click() Dim cn As ADODB.Connection Dim rs As ADODB.Recordset Dim StSQL As String Set cn = CurrentProject.Connection Set rs = New ADODB.Recordset strSQL = "INSERT INTO マスタ(コード) VALUES(コード) ;" rs.Open strSQL, cn, , adLockOptimistic '//前のコード(エラーになりました。) ' rs.Close 'cn.Close 'Set rs = Nothing 'Set cn = Nothing Set rs = Nothing: Close Set cn = Nothing: Close Accessを使用したvbaのコードの書き方について教えてほしいです。毎度Access の質問ばかりしてすみません。以下のコードはADOを使用してマスタというテーブルを読み込んで最後にrs.CloseでRecordSetを開放しようとしたのですが「オブジェクトが閉じている場合は、操作は許可されません。」というエラーメッセージが出てしまい原因がわかりませんでした。Openしていて開いているはずなのにエラーが出てしまい、 Set rs = Nothing: Closeに変えたら治りました。何故rs.Closeではエラーが出てしまったのでしょうか。 もう一つお聞きしたいです。 strSQL = "INSERT INTO マスタ(コード) VALUES(コード) ;"でコードという名前を付けたテキストボックスの値をマスタテーブルのコードの列に追加したいのですがテキストボックスの値の取り方が分かりません。(コード.Value)とやってみてもだめでした。どうやったらSQL文でテキストボックスの値をテーブルに追加できるんでしょうか。

  • アクセス VBAのエラー

    以下のコードをwindowsXPで問題なく使っていましたが、windows7で使ったところ 「保存できません」というエラーメッセージが出ます。ただ全く同じコードを(だと思うのですが)リストボックスのダブルクリックで実行すると作動します。参考に二つのコードを書いておきます。 何か原因に心当たりのある方よろしくお願いします。 (コマンドボタン) Private Sub コマンド選択_Click() Dim namecode As String namecode = リスト会員 Dim cn As New ADODB.Connection Dim rs As New ADODB.Recordset Set cn = CurrentProject.Connection rs.Open "MT_会員", cn, adOpenKeyset, adLockOptimistic rs.Find "会員IDkai = " & namecode rs!Selectedkai = True '-1 rs.Save Me!リスト会員.Requery リスト印刷会員.Requery rs.Close: Set rs = Nothing cn.Close: Set cn = Nothing End Sub (ダブルクリック) Private Sub リスト会員_DblClick(Cancel As Integer) Dim namecode As String namecode = リスト会員 Dim cn As New ADODB.Connection Dim rs As New ADODB.Recordset Set cn = CurrentProject.Connection rs.Open "MT_会員", cn, adOpenKeyset, adLockOptimistic rs.Find "会員IDkai = " & namecode rs!Selectedkai = True '-1 rs.Save Me!リスト会員.Requery リスト印刷会員.Requery rs.Close: Set rs = Nothing cn.Close: Set cn = Nothing End Sub

  • 数値のMAXの値を取得したい ADO VBA

    アクセスです。 ADOで該当のフィールドの数値のMAXの値を取得するにはどうすればいいですか? テーブルの番号フィールドには、 1 2 3 4 5 と入っているのですが、 この場合、一番大きい値は5なので MAX関数のようなもので5を返したいのですが ADOにそのようなプロパティはありますか? オブジェクトブラウザーでRecordsetを見てみましたが 見つけられませんでした。 Sub Sample() Dim cn As New ADODB.Connection Dim rs As New ADODB.Recordset Set cn = CurrentProject.Connection rs.CursorLocation = adUseClient rs.Open "SELECT * FROM T_test", cn, adOpenStatic, adLockPessimistic rs.Sort = "番号 DESC" Debug.Print rs("番号").Value rs.Close: Set rs = Nothing cn.Close: Set cn = Nothing End Sub これで同じような動きは出来ますが、 もっとシンプルにできませんか?