FrontPage 新規 編集 検索 一覧 ヘルプ

ADO

ADO(ActiveX Data Object)メモの目次

使用しているADOのバージョンは?

ConnectionオブジェクトのVersionプロパティの値を参照します。以下を拡張子.vbsの適当なファイルに保存してダブルクリックしてください。

 Option Explicit
 ' adover.vbs - 使用しているADOのバージョンを調べる
 Dim objCon
 Set objCon = CreateObject("ADODB.Connection")
 WScript.Echo "ADO Ver." & objCon.Version
 Set objCon = Nothing

DBへの接続

一番お手軽な VBS+MDBでの接続例

 Dim objCon
 
 Set objCon = WScript.CreateObject("ADODB.Connection")
 With objCon
     .Provider = "Microsoft.Jet.OLEDB.4.0"
     .Open "Northwind.mdb"
 End With

こんな感じで接続できます。接続されると.ldbというテンポラリファイルができるので確認してみましょう。

ADOXでMDBを作成する

日常の開発でこれが必要な状況ですが、

くらいでしょうか。私は後者の事情でたまに利用しますが、普段はあまり必要性は感じません。さておき、サンプルコードです。Catalogオブジェクトを使います。

 Dim objCat
 Set objCat = CreateObject("ADOX.Catalog")
 objCat.Create "Provider=Microsoft.Jet.OLEDB.4.0;" & _
               "Data Source=hoge.mdb;"
 Set objCat = Nothing

これだけです。この例ではカレントにhoge.mdbを作ります。Data Sourceで絶対パスを指定してもいいし、相対アドレスでもOKです。

テーブル作成

上記で作成したmdbにテーブルはありませんので、テーブルも生成してあげる必要がありますよね。幾通りかやり方がありますが、ADOXで作成する方法をとりあえず書いておきます。上で作成したhoge.mdbにTサンプルというテーブルを作成することを想定しています。

 Const adVarWChar = 202
 
 Dim objCat, objTbl
 Set objCat = CreateObject("ADOX.Catalog")
 objCat.ActiveConnection = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
              "Data Source=hoge.mdb;"
 
 Set objTbl = CreateObject("ADOX.Table")
 objTbl.Name = "Tサンプル"
 With objTbl.Columns
    .Append "本名", adVarWChar
    .Append "ふりがな", adVarWChar
    .Append "性別", adVarWChar
 End With
 
 objCat.Tables.Append objTbl
 
 Set objTbl = Nothing
 Set objCat = Nothing

オートナンバー型フィールドの作成

オートナンバー型フィールドを作るのは少々面倒です。ADOX.Column でオートナンバー用のフィールドを定義してから、前述のAppendでこのオブジェクトを渡してあげるとうまくいきます。

以下はT_LogテーブルにLogIdというオートナンバー型フィールドを定義しています。

 Set objCol = CreateObject("ADOX.Column") 
 With objCol
     .Name = "LogId" 
     .Type = adInteger
     Set .ParentCatalog = objCat
     .Properties("AutoIncrement") = True 
 End With 
 
 Set objTbl = CreateObject("ADOX.Table")
 objTbl.Name = "T_Log"
 With objTbl.Columns
     .Append objCol
     .Append "Time", 7
     .Append "Kind", 202, 10
     .Append "Mess", 202, 255
 End With

主キーの設定

ADOXのKeyオブジェクトを使う方法をのせておきます。LogIdを主キーにします。adKeyPrimary はADOX定数です。

 Dim objKey
 Set objKey = CreateObject("ADOX.Key")    
 objTbl.Keys.Append "PrimaryKey", adKeyPrimary, "LogId"
 Set objKey = Nothing

テーブル削除

 Option Explicit
 
 Const DSN = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=hoge.mdb;"
 
 Dim objCat
 Set objCat = CreateObject("ADOX.Catalog")
 objCat.ActiveConnection = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
              "Data Source=hoge.mdb;"
 objCat.Tables.Delete "Tサンプル"
 Set objCat = Nothing

レコードセットのページング処理について

ASPなどでDBを扱う場合重宝する技ですよね。1ページに何レコード表示するとか、検索結果は何ページ存在するとか、そんな感じの処理がADOでは簡単に利用できます。

肝となるのは、

です。

下のサンプルはNorthwind.mdbの仕入先テーブルをページング処理しています。(10レコードづつ区切った4ページ目を表示します)

タイプライブラリのことはVBSのページを参考にしてください。

 Option Explicit
 ' ページング処理のサンプル
 Dim objRec
 Set objRec = CreateObject("ADODB.RecordSet")
 objRec.ActiveConnection = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=Northwind.mdb;"
 objRec.CursorType = 3      ' adOpenStatic
 objRec.Open "SELECT * FROM 仕入先"
 
 objRec.PageSize = 10
 objRec.AbsolutePage = 4
 
 Dim strRes, intCnt, objFld
 intCnt = 1
 Do While (Not objRec.EOF) and (intCnt <= objRec.PageSize)
     For Each objFld in objRec.Fields
         strRes = strRes & objFld.Value & ","
     Next
     strRes = strRes & vbCrLf
     objRec.MoveNext
     intCnt = intCnt + 1
 Loop
 
 MsgBox strRes
 
 objRec.Close
 Set objRec = Nothing

もっと詳しい情報がMSDNに記載されています。参考にしてください。

ASP からのレコードをページングする

JROによるMDBの最適化について

非常に簡単です。VBSのサンプルを載せておきます。サンプルは古い(元の)hoge.mdbを最適化して、新しいhogehoge.mdbを作成します。

動作には、Microsoft Jet and Replication Objects 2.1 Library が必要です。

 Option Explicit
 
 Dim strOld, strNew
 Dim objJRO
  
 strOld = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=hoge.mdb"
 strNew = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=hogehoge.mdb"
 
 Set objJRO = CreateObject("JRO.JetEngine") 
 objJRO.CompactDatabase strOld, strNew
 
 Set objJRO = Nothing

テキストデータへのアクセス方法

CSV形式などテキストデータで保存されたファイルへADOからアクセスするやりかたです。テキストをデータベースとして扱う時は、

のように構成します。

schema.iniについて

schema.iniはテキストファイルをデータベースとして扱うときの各テーブルのスキーマを定義しておくファイルです。テキストデータベースと同じディレクトリに置きます。例えば、

schema.ini

 [会員マスタ.txt]
 ColNameHeader=True
 Format=Delimited(,)
 MaxScanRows=0
 CharacterSet=OEM
 Col1=ID Integer
 Col2=氏名 Char Width 20
 Col3=年齢 Integer
 Col4=性別 Char Width 2
 Col5=入会日 Date(yyyy/mm/dd) Width 8 

のようになります。複数テーブルがあるときは、続けて記入します。指定方法などMSDNにschema.iniの仕様が掲載されているので参考にしてください。

Schema.ini File

サンプル

接続文字列には、Extended Properties=TEXT; がつきます。Data Sourceはディレクトリ名(データベース名)です。下記サンプルではカレントにあるtextdbというディレクトリにアクセスしています。テーブル名は[会員マスタ#TXT] というように、.が#に置き換わり[]で囲むのがお約束です。下記サンプルは、textdbディレクトリ下の会員マスタ.txtの内容を表示します。

textado.vbs

 Option Explicit
 ' CSVをJetで読む
 Dim objRec
 Set objRec = CreateObject("ADODB.RecordSet")
 With objRec
     .ActiveConnection = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
                         "Data Source=textdb;Extended Properties=TEXT;"
     .Open "SELECT * FROM [会員マスタ#TXT]"
     WScript.Echo .GetString(,,", ")
     .Close
 End With
 Set objRec = Nothing

会員マスタ.txt

 ID,氏名,年齢,性別,入会日
 10001,穂下山風太郎,33,男,2002/12/12
 10002,明日来臓,22,男,2002/9/9
 10003,春日未来,18,女,2000/8/25
 10004,鈴木りんご,42,女,2003/6/18

メモリ内でRecordsetを作成してオープンする

これはADO独自の仕様ですが、ようするにデータベースが無くてもRecordsetを作成、利用できます。やり方はいたってシンプルで、単純にRecordsetオブジェクトを作成するだけです。作成後は通常の接続と同様にFieldオブジェクトで操作することができます。

下記サンプルは、メモリ内にRecordsetを作成し、3レコードのデータを追加し、追加したデータをXML形式でカレントフォルダに書き出します。

 <job id="inmemrs">
 <reference object="ADODB.Recordset" />
 <script language="VBScript">
 '--------------------------------------------------------------------
 Option Explicit
 '
 ' inmemrs.wsf - インメモリでrecordsetを作成してオープンする
 '
 Dim objRec, varFields
 Set objRec = CreateObject("ADODB.Recordset")
 varFields  = Array("BookID", "Title", "Price")
 
 With objRec
     With .Fields
         .Append varFields(0), adInteger
         .Append varFields(1), adChar, 100
         .Append varFields(2), adCurrency
     End With
 
     .Open
     .AddNew varFields, Array(100, "HogeHoge", 1200)
     .AddNew varFields, Array(101, "FugaFuga", 1400)
     .AddNew varFields, Array(102, "FooVar",    900)
     .Update
 End With
 
 objRec.Save "sample.xml", adPersistXML
 
 Set objRec = Nothing
 '--------------------------------------------------------------------
 </script>
 </job>

レコードセットの切断

スタンドアローンのアプリケーションでは有難みを感じませんが、ASPなどのクライアント、サーバアプリケーションを作成するなら、このようなテクニックを持っていると有利です。一見すると何も変わったことをしていないようですが、レコードセットをオープン後すぐに接続を切断しています。

 Set objRec.ActiveConnection = Nothing

しかし既にクライアントメモリ内にレコードセットが取得されているので、切断後も表示することができます。(更新以外ならなんでもできる)

ASPなどでレコードセットを利用する場合、このテクニックを使わないと(レコードセットを使用中接続を保ったままにする)と同時アクセスが多い場合はアウトです。接続中レコードセットをサーバで保持しなければならなくなりサーバリソースを消費するからです。

 Option Explicit
 ' disconrs.vbs - レコードセットの切断
 Dim objRec
 Set objRec = CreateObject("ADODB.Recordset")
 objRec.CursorLocation = 3   ' adUseClient
 objRec.Open "運送会社", "File Name=nw.udl"
 Set objRec.ActiveConnection = Nothing
 
 WScript.Echo objRec.GetString
 
 objRec.Close
 Set objRec = Nothing

テーブルの存在をチェック

存在チェックは一時テーブル作成時などによく使います。

テーブルが存在しているかどうかをチェックするには、OpenSchemaでデータベースのスキーマ情報をレコードセットで取得し、取得したレコードセットを調べます。OpenSchemaは引数によって、殆どのDBスキーマ情報を取得できます。テーブル情報の取得には、adSchemaTable = 20 を使用します。

下記サンプルは、チェック部分を関数化したものです。TABLE_TYPEの制約を使用して効率的に処理する方法です。テーブルが存在するならTrueをしないならFalseを返します。

 Option Explicit
 ' tblchk.vbs - テーブルの存在をチェックする
 
 Const adSchemaTable = 20
 Const CONN = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=hoge.mdb;"
 Const TableName = "Tサンプル"
 
 
 If isExistsTable(TableName) Then
     WScript.Echo "テーブル「" & TableName & "」は存在します。"
 Else
     WScript.Echo "テーブル「" & TableName & "」は存在しません。"
 End If
 
 ' テーブルの存在をチェック
 Function isExistsTable(strTableName)
     Dim objCon, objRec
     Set objCon = CreateObject("ADODB.Connection")
     objCon.Open CONN
 
     ' TABLE_TYPE制約を使用
     Set objRec = objCon.OpenSchema(adSchemaTable, _
                             Array(Empty, Empty, Empty, "TABLE"))
 
     isExistsTable = False
     Do Until objRec.EOF
         If strTableName = objRec("TABLE_NAME") Then isExistsTable = True
         objRec.MoveNext
     Loop
 
     objRec.Close : Set objRec = Nothing
     objCon.Close : Set objCon = Nothing
 End Function

同じことをADOXを使ってやるとこうなります。

 ' ADOXを使ったテーブルの存在チェック
 Function isExistsTable(strTableName)
     Dim objCat, objTable
     Set objCat = CreateObject("ADOX.Catalog")
     objCat.ActiveConnection = CONN
 
     isExistsTable = False
     For Each objTable In objCat.Tables
         If objTable.Type = "TABLE" Then
             If objTable.Name = strTableName Then
                 isExistsTable = True
                 Exit For
             End If
         End If
     Next
 
     Set objCat = Nothing
 End Function

バイナリデータの読み書き

ADOはDB操作しか出来ないと思われ勝ちですが、ADO Streamオブジェクトを使うと、テキストデータやバイナリデータの入出力を行うことができます。VBScriptでのテキストデータ処理はFileSystemObjectでもサポートしているので、あまりありがたみを感じませんが、バイナリデータを扱えるのは非常にありがたいことです。

サンプルはカレントの hoge.jpg を backup_hoge.jpg というファイル名でコピーします。

 Option Explicit
 ' バイナリファイルの読み書きテスト
 Const adTypeBinary = 1
 Const adSaveCreateOverWrite = 2
 
 Const FILE  = "hoge.jpg"
 
 Dim objStream
 Set objStream = CreateObject("ADODB.Stream")
 
 objStream.Open
 objStream.Type = adTypeBinary
 
 objStream.LoadFromFile FILE
 objStream.SaveToFile "backup_" & FILE, adSaveCreateOverWrite
 objStream.Close
 Set objStream = Nothing

このサンプルはちょっとズルっこで、バイナリデータを読み込んでそのまま別名で保存してます。実際にバイナリデータを読み書きするには、read, writeというメソッドを使います。

レコードセットの永続化

読み出したレコードセットをファイルに保存し、後で保存したレコードセットを読み出して使ったりします。結構便利。下記サンプルは、運送会社テーブルの内容を表示し、それをADTG形式でファイルに保存します。そして一度レコードセットを閉じインスタンスを廃棄します。その後、再びレコードセットのインスタンスを作成し保存したレコードセットを読込み、表示します。

 <job>
 <reference object="ADODB.Recordset" />
 <script language="VBScript">
 Option Explicit
 ' レコードセットの保存と保存したレコードセットの読込み
 Const SAVENAME  = "data.adtg"
 
 Dim objRec
 Set objRec = CreateObject("ADODB.Recordset")
 
 objRec.Open "運送会社", "File Name=nw.udl", _
             adOpenForwardOnly, adLockReadOnly, adCmdTableDirect
 
 WScript.Echo objRec.GetString
 
 On Error Resume Next
 CreateObject("Scripting.FileSystemObject").GetFile(SAVENAME).Delete
 On Error Goto 0
 
 'レコードセットをADTG形式で保存
 objRec.Save SAVENAME, adPersistADTG
 objRec.Close
 Set objRec = Nothing
 
 
 ' 時が過ぎ・・・ 
 Set objRec = CreateObject("ADODB.Recordset")
 
 '保存したレコードセットを開く
 objRec.Open SAVENAME
 WScript.Echo objRec.GetString
 objRec.Close
 Set objRec = Nothing
 </script>
 </job>

非同期接続

データベースに非同期で接続する技です。通常デフォルトの同期接続になりますが、データベースに接続している間に別の作業をすることができるので、非同期にするだけでアプリケーションが劇的に速くなることもあります。やり方は簡単で、ConnectionオブジェクトのOpenメソッドで、第4引数に adAsyncConnect を指定することで非同期接続になります。非同期接続にすると接続を待たずに即次行からの処理を行います。

さて、非同期な(接続を待たない)ので繋がったかどうかの確認が必要となります。VC++やVB、VBAなら、ADOのイベントをトリガして接続を確認できます。=VBSではADOイベントを利用できないので、ConnectionオブジェクトのStateプロパティの値を読んで接続したかどうかを判断すればよいでしょう。= (実はVBSでも利用できます。やり方はVBSのページで)

サンプルはASPです。nw.udlで指定したDBに非同期接続を試みます。接続中に .... と表示していき、接続成功すると"接続しました!"と表示します。

 <!-- METADATA TYPE="TypeLib" UUID="00000205-0000-0010-8000-00AA006D2EA4"-->
 <% @LANGUAGE="VBSCRIPT" %>
 <% Option Explicit %>
 <html>
 <head>
 <title>非同期接続サンプル</title>
 </head>
 <body>
 <%
 Dim objCon
 Set objCon = Server.CreateObject("ADODB.Connection")
 objCon.Open "File Name=" & Server.MapPath("nw.udl"), , , adAsyncConnect
 
 Response.Write "接続中"
 While Not objCon.State = adStateOpen
     Response.Write "."
 Wend
 Response.Write "接続しました!"
 
 objCon.Close
 Set objCon = Nothing
 %>
 </body>
 </html>
Yesterday Today Total