VBAでODBC APIを直接使う例
最終更新日:2000/10/09
 

'
'VisualBasic による ODBC API の使用例
'
'【解説】
'  通常、VBA によって、ODBC API を直接使う必要性は、
'まずありません。
'ただ、使った場合、どの程度のものになるか、
'知っておく事も、無駄ではないかと思います。
'一般に、ミドルウエアは、機能が多く盛り込まれる為、
'結果的に、内部で無駄な操作が行われ、予期した結果に
'ならない場合が、時々見うけられます。
'
'この例では、API との関連を理解しやすいように、
'なるべく API を直接呼ぶように、処理を行っていますが、
'実用的に使おうと考えれば、サブルーチン化または、
'クラス(DLL)化する事を考えたほうが良いと思います。
'
'【処理内容】
'  テーブルを作成し、データを挿入後、表示し、
'最後にテーブルを消します。
'この例では、select 文のカラム数や型が、予め解っていない
'動的SQL処理にも対応出来るようになっています。
'その分、多少冗長になっています。
'
'【実行手順】
'  VB5 以上、ODBC 3.0 以上が必要です。
'プロジェクトに「フォーム」と、「標準モジュール」を
'追加し、フォームには、ボタンとを1つ作成して、
'それぞれに、以下のコードを記述して下さい。
'また、コード中の、データソース名、ユーザー名、
'パスワードも、動作する環境のものに変更して下さい。
'(ユーザーにはテーブル作成の権限が必要です)
'

Private Sub Command1_Click()
    Dim henv As Long
    Dim hdbc As Long
    Dim hstmt As Long
    
    Dim rc As Integer 'ReturnCode
    Dim sqlstate As String * 10
    Dim nativerr As Long
    Dim errmsg As String * 256
    Dim errmsglen As Integer
    
    Dim nCol As Integer
    Dim colname As String * 32
    Dim namelen As Integer
    Dim sqltype As Integer
    Dim colsize As Long
    Dim deci As Integer
    Dim nullind As Integer
    
    Dim valint As Long
    Dim valstr As String * 256
    Dim longind As Long
    
    Dim sqldata() As SQLDA
    
    '(1) 環境の準備
    'なぜか HDBC の作成でエラーになるので、旧 API を使用しました
    'rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, henv)
    rc = SQLAllocEnv(henv)
    rc = SQLAllocHandle(SQL_HANDLE_DBC, henv, hdbc)
        
    '(2) データベース接続
    '  データソース名、ユーザー名、パスワード
    rc = SQLConnect(hdbc, _
        "oracle1", SQL_NTS, _
        "baba", SQL_NTS, _
        "baba", SQL_NTS)
    
    'エラーハンドリングの例
    If rc = SQL_ERROR Then
        Call SQLGetDiagRec( _
            SQL_HANDLE_DBC, hdbc, 1, sqlstate, _
            nativerr, errmsg, 255, errmsglen)
        MsgBox errmsg
        Exit Sub
    End If
    
    '(3) SELECT以外のダイナミック(全て文字列)なSQLの実行
    '    これらは簡単です
    'テーブル作成
    rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, hstmt)
    rc = SQLExecDirect(hstmt, _
        "create table odbc_test (i1 integer, a1 varchar(10))", SQL_NTS)
    rc = SQLFreeHandle(SQL_HANDLE_STMT, hstmt)
    
    'INSERT
    rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, hstmt)
    rc = SQLExecDirect(hstmt, _
        "insert into odbc_test values(123,'abc')", SQL_NTS)
    rc = SQLFreeHandle(SQL_HANDLE_STMT, hstmt)
    
    '(4) SELECT 文の実行
    '    これはちょっと厄介です
    'ここでは、後々応用が効くように、ダイナミックSQLに対応します。
    'カラム情報として、SQLDA 構造体(動的配列)を独自に定義しています。
    'クラス化の際は、コレクションにすれば、より操作性が向上します。
    rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, hstmt)
    
    '(4-1) ステートメントの解析
    rc = SQLPrepare(hstmt, _
        "select * from odbc_test", SQL_NTS)
    
    '(4-2) 結果を受け取るカラム数の取得
    rc = SQLNumResultCols(hstmt, nCol)
    
    '(4-3) SQLDA(配列)にカラム情報を転記します
    ReDim sqldata(nCol)
    For i = 1 To nCol
        rc = SQLDescribeCol(hstmt, _
         i, colname, 32, namelen, sqltype, _
         colsize, deci, nullind)
        sqldata(i).name = Left(colname, namelen)
        sqldata(i).sqltype = sqltype
        sqldata(i).sqllen = colsize
    Next
        
    '(4-4) ステートメント(SELECT)の実行
    rc = SQLExecute(hstmt)
    
    '(4-5) 結果行の取得と表示
    rc = SQLFetch(hstmt)
    While rc = SQL_SUCCESS Or rc = SQL_SUCCESS_WITH_INFO
        For i = 1 To nCol
            'ここでは、単純化の為、2つのタイプしか扱っていませんが
            '本来は、扱うデータタイプの全てを記述します
            sqltype = sqldata(i).sqltype
            
            'Oracle の場合、SQL_DECIMAL が返る事があります。
            If sqltype = SQL_INTEGER Or _
               sqltype = SQL_DECIMAL Then
                rc = SQLGetData(hstmt, _
                i, SQL_C_LONG, VarPtr(valint), 4, longind)
                sqldata(i).val = valint
            End If
            
            If sqltype = SQL_VARCHAR Then
                rc = SQLGetData(hstmt, _
                i, SQL_C_CHAR, valstr, 255, longind)
                sqldata(i).val = valstr
            End If
        
        Next
        
        '表示処理
        For i = 1 To nCol
            MsgBox sqldata(i).name & "=" & sqldata(i).val
        Next
        rc = SQLFetch(hstmt)
    Wend

    rc = SQLFreeHandle(SQL_HANDLE_STMT, hstmt)
    
    '(5) 終了処理
    'テーブルの後始末
    rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, hstmt)
    rc = SQLExecDirect(hstmt, _
        "drop table odbc_test", SQL_NTS)
    rc = SQLFreeHandle(SQL_HANDLE_STMT, hstmt)
    
    '接続解除
    rc = SQLDisconnect(hdbc)
    rc = SQLFreeHandle(SQL_HANDLE_DBC, hdbc)
    rc = SQLFreeHandle(SQL_HANDLE_ENV, henv)
End Sub

    標準モジュールのソース

|HOME|戻る|