Access

【AccessVBA】ADOとDAOを使ってレコードセットを読み書きする方法

レコードセット
記事内に商品プロモーションを含む場合があります

AccessのVBAでレコードを操作したいときに利用するレコードセット。

レコードセットを使ってデータベースを読み書きする方法はADO接続とDAO接続があります。

ADO・DAOどちらを使うべきか

古くから実装されているのがDAOで、後発の接続方法としてADOが利用できるようになりました。

DAOもAODもほぼ同じことができるので基本的には処理速度が速い方がいいですよね

一般的には以下のように言われています。

Accessのテーブルを操作する場合はDAOの方が速い

その他のDBへ外部接続したテーブルを操作する場合はADOの方が速い

DAOはAccessのJETエンジンに特化した接続であるため、ACCESSのテーブルへのアクセスがADOより高速です。

しかし、高速と言っても若干高速ぐらいですので、やりやすい方法で実装し実際の検索があまりにも遅い時にチューニングとしてDAOとAODを切り替えてみるというレベルで良いのでは?と思います。

そもそも極端に遅い場合はDAOだ、ADOだという前にSQLの構成に問題がある場合もありますので・・・。

ADO,DAOのレコードセットの使用方法

今回は顧客テーブルから誕生月が3月ユーザーを検索してプレゼント発送日を更新するという処理を想定してみました。

要するに検索+更新のレコードセット操作方法です。

DAO接続によるレコードセット操作

Private Function DAO接続() As Boolean

    Dim myDb    As DAO.Database     'データベースオブジェクト
    Dim myRs    As DAO.Recordset    'レコードセットオブジェクト
    Dim strSQL  As String       'SQL文用文字列
    
    'エラートラップ
    On Error GoTo Err_Exit
    
    '関数の戻り値初期化
    DAO接続 = False
    
    Set myDb = CurrentDb '現在のデータベースをセット
    
    'SQL文作成(誕生月指定)
    strSQL = "SELECT * FROM 顧客テーブル WHERE 誕生月 = 3"
    
    'レコードセット取得
    Set myRs = myDb.OpenRecordset(strSQL)
  
    With myRs
        '対象データがなければ終了
        If .EOF Or .BOF Then
            MsgBox "該当データがありません。処理を終了します。", vbOKOnly + vbInformation
            GoTo End_Proc
        Else
            '先頭レコードに移動
            .MoveFirst
            While Not .EOF
                '対象データを編集モードにする
                .Edit
                'プレゼント発送日にシステム日付を代入
                .Fields("プレゼント発送日") = Date
                '更新実行
                .Update
                '次のレコードに移動
                .MoveNext
            Wend
        End If
    End With
    MsgBox "処理を終了しました。", vbOKOnly + vbInformation
    
End_Proc:
    'オブジェクトの開放
    Set myRs = Nothing: Close
    Set myDb = Nothing: Close
    
    '正常終了
    DAO接続 = True
    
    Exit Function
  
Err_Exit:
    'エラーNOとエラーの詳細を表示
    MsgBox Err.Number & ":" & Err.Description, vbOKOnly + vbCritical, "DAO接続()"
    'オブジェクトの開放
    Set myRs = Nothing: Close
    Set myDb = Nothing: Close
  
End Function

ADO操作によるレコードセット操作

Private Function ADO接続() As Boolean

    Dim myCn     As ADODB.Connection    'ADOコネクションオブジェクト
    Dim myRs     As ADODB.Recordset     'ADOレコードセットオブジェクト
    Dim strSQL   As String              'SQL文用文字列
    
    'エラートラップ
    On Error GoTo Err_Exit
    
    '関数の戻り値初期化
    ADO接続 = False
    
    '現在のデータベースへ接続
    Set myCn = CurrentProject.Connection
    
    'ADOレコードセットのインスタンス作成
    Set myRs = New ADODB.Recordset
    
    'SQL文作成(誕生月指定)
    strSQL = "SELECT * FROM 顧客テーブル WHERE 誕生月 = 3"
    
    'レコードセット取得・・・(※1)
    myRs.Open strSQL, myCn, , adLockOptimistic
  
    With myRs
        '対象データがなければ終了
        If .EOF Or .BOF Then
            MsgBox "該当データがありません。処理を終了します。", vbOKOnly + vbInformation
            GoTo End_Proc
        Else
            '先頭レコードに移動
            .MoveFirst
            While Not .EOF
                'プレゼント発送日にシステム日付を代入
                .Fields("プレゼント発送日") = Date
                '更新実行
                .Update
                '次のレコードに移動
                .MoveNext
            Wend
        End If
    End With
    MsgBox "処理を終了しました。", vbOKOnly + vbInformation
    
End_Proc:
    'オブジェクトの開放
    Set myRs = Nothing: Close
    Set myCn = Nothing: Close
    
    '正常終了
    ADO接続 = True
    
    Exit Function
  
Err_Exit:
    'エラーNOとエラーの詳細を表示
    MsgBox Err.Number & ":" & Err.Description, vbOKOnly + vbCritical, "ADO接続()"
    'オブジェクトの開放
    Set myRs = Nothing: Close
    Set myCn = Nothing: Close
  
End Function

ADO接続の場合、参照設定が必要です。

参照設定されていない場合、実行時以下のエラーが表示されます。

参照設定エラー

ツールの参照設定から、【ActiveX Data Objects x.x Library】にチェックを入れてください。(お使いの環境において最新のライブラリーにチェックしてください)

ADO参照設定

※1 ADOのOpenメソッドのロックタイプ規定値は読み取り専用(adLockReadOnly)となっていますので、adLockOptimisticを指定する必要があります。

参考:Microsoft公式サイト

ADOとDAOの違いで気を付ける点

編集前のeditコマンド

DAOの場合、レコードを更新する際は事前に.editコマンドで編集することを宣言する必要がありますが、ADOの場合は不要です。

取得したレコードセットからデータを抽出する方法

その他、一旦取得したレコードセットからさらにデータを抽出する方法としてfindコマンドがありますが、DAOの場合は複数のフィールドに対して条件を指定できますがADOで指定できる条件は1つだけです

このため複数の条件を指定したい場合はADOの場合filterプロパティを使用します。

通常、条件を指定してレコードセットを取得するものですが、それなりの事情があって一旦取得したレコードセットからさらに絞り込む場合です。

レコードセットの検索
【AccessVBA】レコードセットからデータを検索する方法(find or filter)ADOやDAOで取得したレコードセットからデータを絞り込んで検索する方法にはfindコマンドを使う方法があります。 ただ、ADOで...
ABOUT ME
アズビーパートナーズ
プログラマー→社内SE→SIerのお仕事をしています。 メーカー勤務を経て、中小企業の社内SE、フリーランスなど様々な形態で働いてきました。 業務上生まれた困った…を解決してきたTipsを備忘録も兼ねて公開しています。 困っている誰かのお役に立てれば幸いです。