DAOとは、Data Access Objectsの略でMicrosoft社が開発したデータベース接続(データベースアクセス)用プログラミングインタフェースであり、VB、VCなどMicrosoft製プログラミング言語から利用されますが、ローカル接続に長けており、主にAccess VBA/Excel VBA/VBで利用されます。
DAOは、Microsoft社のRDBアプリAccessのデータベース接続インタフェースでもあるJetデータベースエンジンを利用したMS Accessの.mdbファイルへの接続や、やはり当初MS社が開発、その後、オープン仕様となった汎用データベース接続インタフェースであるODBCを経由したRDBデータベースサーバへの接続、また、ExcelやSQL Server、dBASE/Paradox/Microsoft Oracle ODBCなどISAM/Indexed Sequential Access Methodを採用したDBや、更にはテキストファイルに直接接続することができます。
DAOを利用する為には、AccessやExcel VBAやVB6.0では、GUIエディタのメニューから参照設定を行い、『Microsoft DAO ? Object Library』を指定します(「?」にはバージョンが入ります)。
尚、VBやVBA、そのバージョンによって参照が異なる場合もありますし、選択基準も機能ごとだけでなくVB/VBAの異なるバージョンを利用する為に参照するケースもあり、他方、通常複数のライブラリが参照された状態が普通であり、ライブラリ相互に依存関係や場合によっては競合関係がある場合もあり、他の参照が必要、例外的に他の参照を外す必要が出てくる可能性もあります。
object.method
object.property
DAOのオブジェクトにおけるメソッド、プロパティは、オブジェクトに続けてドット、メソッド名またはプロパティ名と記述することによって指定または参照します。
かなり大ざっぱですが、DAOの階層におけるDBEngineの下位には、Workspaces、更にその下位にWorkspaceがあり、そのWorkspaceの下位には、Connectionsの下位にConnectionやDatabasesの下位にDatabaseオブジェクトがあり、更にその下層にRecordsets...と連なっています。
英語表記における複数形のsがつくものは、各Object(オブジェクト)を包含するCollection(コレクション)と呼ばれており、特殊なケースを除き、普通はsのつかない通常のオブジェクトを記述し、使用します。
また、Workspaces/Workspaceオブジェクトは多重に開く(多次元配列)ことができ、既定及び最初に開くWorkspaceはWorkspaces(0)で順次Workspaces(1)、Workspaces(2)、また、Workspaces(0)(0)、Workspaces(0)(1)と宣言することで各作業領域を確保することができる仕様になっていますが、既定でWorkspaces(0)として1つだけ開く(一般的な使用方法の)場合にはsの付かないDAO.Workspaceで記述するか、一切書かずに省略することが可能です。
ちなみにこうした階層構造はツリー(木)構造と呼ばれることがあり、出発点である元(DAO階層ではDBEngine)を根っこに喩えてルート(根)と呼び、ルートに比し、使用頻度は格段に少なくなるとは思いますが、ルートからの分岐を枝や葉と呼ぶことがあります(尚、枝をブランチ/branchと呼ぶ場合もある一方、葉をリーフ/leafとする表現はあまり見聞きしない気がしますが、気のせい?)。
DAOを使ってRecordset(テーブルのデータ)にアクセスする方法は、Jet経由とODBC経由で若干異なります。
Jet経由の場合には、Databaseオブジェクトによりデータベースに接続し、Recordsetオブジェクトによって接続したデータベース内のレコードにアクセスするという流れになります。
AccessのMDBファイルにアクセスする際のVB6.0によるコードは、例えば、以下のように記述します。
Jet経由の場合には、DatabaseオブジェクトとRecordsetオブジェクトを使用するので、それぞれの型の変数を宣言します("DAO."の付加を推奨)。
mdbを新規作成する場合には、DAOのオブジェクト階層のルートであるDBEngineのCreateDatabaseメソッドを使用します。
既存のmdbを開く場合には、ルートであるDBEngineのOpenDatabaseメソッドを使用し、引数としてデータベース名(フルパス)を(必要に応じてuser_id/passwordも)渡します。
次にデータアクセスですが、ODBC/Jet何れを経由する場合もデータベース接続後、データ操作言語(DML/Data Manipulation Language)であるselect/insert/update/deleteの内、SQLの結果を取得するselectにはOpenRecordsetメソッド、取得しないinsert/update/deleteにはExecuteメソッドを使います。
Setステートメントで(DAO.DatabaseのOpenRecordsetで)開いたレコードセット(select文の結果)をDAO.Recordsetに割り当てます。
Recordsetが開いている間、select文の結果をSetしたDAO.Recordsetオブジェクト(例ではrs)に1レコードずつアクセスできるのでWhileループなどで各レコード(行)ごとに各データ(列)を個々に参照、取得することができます。
各データ(列)は、レコードごとにリスト(配列)としてDAO.Recordsetオブジェクト(例ではrs)に格納されており、例ではrs(0)、rs(1)...やrs("col_name_A")、rs("col_name_B")...等、丸かっこ内に0から始まる列番号または列名(column/カラム名)を入れた添え字付きで参照することができます。
尚、ループ中の行の移動に利用可否や利用可能な場合のメソッドは、DAOにおいては、DAO.WorkspaceオブジェクトのDefaultCursorDriverプロパティの値によって変わってきます。
使い終わったら開いたDAO.Recordsetを閉じます。
insert/update/deleteの場合、DAO.DatabaseのBeginTransでトランザクションを開始し、SQLは、DAO.DatabaseのExecuteメソッドで発行、DAO.DatabaseのCommitTransで確定、Rollbackで取り消します。
db.BeginTrans ' トランザクションの開始
db.CommitTrans ' コミットすることでデータベースに反映される
ちなみに、Executeメソッドの引数を括る外側のカッコは省略も可能です。
尚、SQL文をあらかじめ変数にセットしてからExecuteメソッドに渡すこともできます。
db.BeginTrans
db.CommitTrans
使い終わったら開いたDAO.Databaseを閉じます。
尚、DAO.Workspaceオブジェクトを利用する必要がある場合には、下記のようなコードを追加します。
CreateWorkspace()メソッド
【第4引数】dbUseJetは、Jetデータベースエンジンを利用する場合の定数
同メソッドをODBCで利用する場合には、この引数はdbUseODBCです。
というわけでJet経由のDAOによるアクセスは下記のようになります。
' 例)VB6.0 Jet経由
Sub DB_Open_via_Jet()
...
...
' insert/update/delete文の場合
db.BeginTrans
db.CommitTrans
...
END Sub
CreateDatabase()メソッド
【第1引数】db_name:必須
MS AccessのMDBファイルのフルパス(上限255文字)
【第2引数】Connect:必須
照合用パスワードやlocale(国・地域*localではなくlocale)文字列を指定
例)dbLangJapanese & ";pwd=NewPassword"
【第3引数】Option:オプション:下記は設定値の選択肢
OpenDatabase()メソッド
【第1引数】db_name:必須
MS AccessのMDBファイル名またはODBCデータソースのDSN/Data Source Name
【第2引数】Option:オプション
True/False(排他モード/共有モード)
*既定はFalse:共有モード
仕様上、第2引数は様々なDB情報設定ができるとありますが...
【第3引数】readonly_flg:オプション
True/False(読み取り専用フラグ)
*既定はFalse:読み取り可/書き込み可
【第4引数】Connect:オプション
パスワードを含む様々な接続情報
ODBC経由のDAOのデータアクセスでは、DBEngineオブジェクト内にWorkspace(作業場所)を確保、そのWorkspace内でConnectionを開き(OpenConnectionメソッド)、ConnectionオブジェクトのOpenRecordsetメソッドでselect文を実行し、その結果をRecordsetオブジェクトにSet、結果セットが不要なInsert/Update/Delete文はWorkspaceオブジェクトのBeginTransメソッドで処理を開始、ConnectionオブジェクトのExecuteメソッドで発行、WorkspaceオブジェクトのCommitTransメソッドで確定/Rollbackメソッドで取り消しするという流れになります。
' 例)VB6.0 ODBC経由
Sub DB_Open_via_ODBC()
...
...
ws.BeginTrans
ws.CommitTrans
...
END Sub
CreateWorkspace()メソッド
【第4引数】dbUseODBCは、ODBCを利用する場合の定数
同メソッドをJetで利用する場合には、この引数はdbUseJetです。
OpenConnection()メソッド
【第1引数】""
カラで可
*複数開く場合の識別子として任意の文字列Connection1、Connection2などを設定
【第2引数】connect_opt :下記は設定値の選択肢
【第3引数】readonly_flg
読み取り専用フラグ
True/False
【第4引数】:odbc_connection_string :ODBC接続文字列
*下記の例は最少要件(例えばDATABASE=name;も付加可能)
*[ ]はオプション/セミコロンはセパレータ/指定時は全体をクォーテーションで括る
*"ODBC"は定数、小文字部分には該当する値を設定
*定数ODBC;以外は順不同
Jet経由におけるDAO.Database.OpenRecordsetまたは、ODBC経由におけるDAO.Connection.OpenRecordsetによって取得したSQL(select文)の結果であるレコードセットを参照、取得する為のループ中のレコード(行)の移動については、カーソルが利用可能か否か、利用可能な場合には、カーソルがサーバ側にあるのか、クライアント側にあるのかによって異なりますが、これらを設定するのがDAOの場合、DAO.WorkspaceのDefaultCursorDriverプロパティです。
...
' DAO.Workspaceのカーソルプロパティ
while rs.EOF = False
DAO.WorkspaceのDefaultCursorDriverプロパティを設定する場合には、当然と言えば当然ですがDBEngine.CreateWorkspaceでWorkspaceを生成した後に設定し(dbUseDefaultCursorの場合は省略可)、設定値とその意味は次の通りです。
' DAO.Workspace.DefaultCursorDriverプロパティ設定値
' DAO.Recordsetのレコード移動用メソッド
ループ中のレコードセット内のレコード移動に利用する為のメソッドは、DAO.Recordsetオブジェクト(例ではrs)のこれら4つですが、全て利用できるのはDAO.Workspace.DefaultCursorDriverプロパティ設定値がクライアントカーソルの時だけで、それ以外で利用できる場合、その多くはMoveNextメソッドだけのようです。
尚、例えばクライアントバッチカーソルを利用する(dbUseClientBatchCursorの)場合、予めレコードセットの全てをクライアント側で保持する必要があり、レコードセットのサイズが大きい場合には、それに応じて取得時のネットワーク上のトラフィック量が増え、メモリ上の格納領域も大きくなるということになります。
また、例えばサーバカーソルを利用する(dbUseServerCursorの)場合、レコードセットのレコードを1行ずつ読み込む為、レコード件数(DAO.Recordset.RecordCount)は全てのレコードを読み込むまで知ることができませんが、dbUseClientBatchCursorの場合は、ループ前に把握することができます。
DAOでODBCを経由する場合は、DAO.Workspace.DefaultCursorDriverプロパティ設定値には、dbUseODBCCursorを設定する必要があるので、DAOでその他プロパティを明示的に設定できるのは、実質Jet経由などODBCを利用しない且つWorkspaceを生成する時だけであり、逆に言うとカーソルを明示的に設定したい場合には、Jet経由(MS Accessの.mdbなど)において必然的にWorkspaceを確保する必要があるということになります。
これらを勘案した上でレコードセットの操作方法を検討することになります。
ちなみにMicrosoftはRDOやDAOに続き、後にADO/ActiveX Data Objectsというデータベース接続を開発・リリースした関係で型が重複するケースや紛らわしいケースを回避する意味も含め、宣言時、明示的にDAO.Workspace/DAO.Connection/DAO.RecordsetのようにDAO.を付加し、他方、ADOも"ADODB."と明示的に付加しADODB.Connectionとし、DAOとADOで重複する場合は必須、そうでない場合も付記することが推奨されています。
DAOのオブジェクトは、ここで挙げた以外にも多々あり、各オブジェクトには、個々に多くのプロパティがありますが、ここでは割愛させて頂きます。
DAOはデータベースサーバへの接続というよりもAccess(.mdb/Microsoft Jet)の特にローカルでの接続、Microsoft Jetで直接読み込むことが可能なExcelやテキストファイル等々、やはりローカル利用に長けていることから、Access VBAやExcel VBA、クライアントサーバシステムのようにネットワークを介したシステムにおいては、とかくクライアントサイドのプログラミング言語であるVBで利用される傾向が強く、それに比し、稀にVC/VC++でも利用されることがあるという位置づけでした。
データベースサーバへの接続は、間もなくリリースされたADOが推奨されましたが、データベースサーバ接続には長けているものの、当初DAOの機能を十分に取り込めなかった、おそらくより正確にはJetの代替技術が未完成、他方Jetとの連携は十分とは云えなかった為、その後しばらくADOとDAOは共存することになります。
実際ADOのリリースからしばらく(Access 97辺りまで?)は、仕様としてADOによるMS Access mdbの更新(INSERT/UPDATE/DELETE)ができず、AccessにはDAO、その他にはADOを利用するようアナウンスしていましたが、後にDAOと同様にJetエンジンを介したADOによるAccess mdbの更新もできるようになっています。
一方、システム構成としてクライアントもUI含めプログラミング言語で開発するクライアントサーバシステムというよりは、ブラウザをクライアントとするウェブシステムが主流となり、クライアントサイドのプログラミング言語がVBであるという発想や存在感は薄くなりましたが、その過程で.NET Framework技術が確立し、VB .NETでは、DAO/RDO/ADOの利用もできるもののADO .NETへのデータバインディングが可能であるのは旧ADOのみです。
また、VCを包含するVC++ .NETでは互換性維持の為にMFCからDAOの参照は可能であるものの、それ以外でDAOを利用する機能はなくなりました(Express/無償版ではMFCの利用ができないので既にVisual VC++ Expressでは実質DAOは利用できません)。
RDOとはODBCのCOMラッパであり、.NET以前のVBを強く意識して作られた経緯も相まって一部機能については高レベル(人間寄りの)言語VBで利用できて低レベル(機械寄りの)アクセスをも担うはずのVC++で利用できない機能もあるなど汎用性に欠ける部分もあるようです。
これらのことからもMicrosoftは実質DAO、RDO技術で可能なことを包含し、シンプルに記述できる上により汎用性が高く、仕様が統一されていてActiveX機能によりウェブとの連携に長けているADO/ADO .NETを一層推奨し、ADO .NETへの集約したい意向のようですが妥当な選択でしょう。