愚者の経験

「また今度」はほとんどこない

VBAからODBC APIを使う 実行編

前の記事:VBAからODBC APIを使う 接続編

データのアクセス部分に入ります。
データを返さないSQL文はSQLExecDirectで実行し、
それ以外はSQLExecuteで実行するといいと思います。

‘ODBC API
Private Declare Function SQLExecDirect Lib “odbc32.dll” ( _
                ByVal hstmt As Long, _
                ByVal szSqlStr As String, _
                ByVal cbSqlStr As Long) As Integer

Private Declare Function SQLPrepare Lib “odbc32.dll” ( _
                ByVal hstmt As Long, _
                ByVal szSqlStr As String, _
                ByVal cbSqlStr As Long) As Integer

Private Declare Function SQLNumResultCols Lib “odbc32.dll” ( _
                ByVal hstmt As Long, _
                ByRef pcCol As Integer) As Integer

Private Declare Function SQLExecute Lib “odbc32.dll” ( _
                ByVal hstmt As Long) As Integer

Private Declare Function SQLDescribeCol Lib “odbc32.dll” ( _
                ByVal hstmt As Long, _
                ByVal iCol As Integer, _
                ByVal ColName As String, _
                ByVal NameLen As Integer, _
                ByRef pNameLen As Integer, _
                ByRef DataType As Integer, _
                ByRef ColSize As Long, _
                ByRef pDecimal As Integer, _
                ByRef pNull As Integer) As Integer

Private Declare Function SQLFetch Lib “odbc32.dll” ( _
                ByVal hstmt As Long) As Integer

Private Declare Function SQLGetData Lib “odbc32.dll” ( _
                ByVal hstmt As Long, _
                ByVal iCol As Integer, _
                ByVal fCType As Integer, _
                ByVal pValue As Any, _
                ByVal BufLen As Long, _
                ByRef pcbValue As Long) As Integer

Private Const SQL_NTS = -3
Private Const SQL_NO_DATA_FOUND = 100

‘データ型(SQLServerのデータ型を試してみた)返り値
Private Const SQL_CHAR = 1
Private Const SQL_NUMERIC = 2
Private Const SQL_DECIMAL = 3
Private Const SQL_INTEGER = 4
Private Const SQL_SMALLINT = 5
Private Const SQL_FLOAT = 6
Private Const SQL_REAL = 7
Private Const SQL_DOUBLE = 8
Private Const SQL_DATETIME = 11
Private Const SQL_VARCHAR = 12
Private Const SQL_VARCHARMAX = -1
Private Const SQL_TIMESTAMP = -2
Private Const SQL_VERBINARY = -4
Private Const SQL_BIGINT = -5
Private Const SQL_TINYINT = -6
Private Const SQL_BIT = -7
Private Const SQL_NCHAR = -8
Private Const SQL_NVARCHAR = -9
Private Const SQL_NVARCHARMAX = -10
Private Const SQL_GUID = -11
Private Const SQL_VARIANT = -150
Private Const SQL_MONEY = SQL_DECIMAL Or SQL_NUMERIC

‘ODBC データ型(何があるのかよくわからない)
Private Const SQL_C_CHAR = SQL_CHAR
Private Const SQL_C_LONG = SQL_INTEGER
Private Const SQL_C_SHORT = SQL_SMALLINT
Private Const SQL_C_FLOAT = SQL_REAL
Private Const SQL_C_DOUBLE = SQL_DOUBLE

Public Sub ExecuteODBC1()
     Const stmt = “insert into table1 values (1,’a’)”
     ‘ステートメントハンドル作成
     Ret = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, hstmt)

     ‘SQL文を実行する
     Ret = SQLExecDirect(hstmt, stmt, SQL_NTS)
End Sub

Public Sub ExecuteODBC2()
    Dim ColDataType As New Collection
    Dim Column As Long
    Dim i As Long
    Dim ColName As String
    Dim NameLen As Integer
    Dim DataType As Integer
    Dim ColSize As Long
    Dim pDecimal As Integer
    Dim pNull As Integer
    Dim pcbValue As Long
    Const stmt = “select * from table1”
    ‘ステートメントハンドル作成
    Ret = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, hstmt)
   
    Ret = SQLPrepare(hstmt, stmt, SQL_NTS)
    Ret = SQLNumResultCols(hstmt, Column)
   
    ‘列の解析
    For i = 0 To Column – 1
        ColName = String$(32, Chr(0))
        SQLDescribeCol hstmt, i + 1, ColName, 32, NameLen, DataType, ColSize, pDecimal, pNull
        ‘ColName  列名 Left$(ColName,Instr(ColName, Chr(0)))
        ‘NameLen 列名の長さ
        ‘DataType データ型
        ‘ColSize    データ長
        ‘あと2つはまだわかりませんm(__)m
        ColDataType.Add DataType, Left$(ColName, InStr(ColName, Chr(0)) – 1)
    Next
   
    ‘SQLの発行
    Ret = SQLExecute(hstmt)
   
    Do Until Fetch(hstmt) = SQL_NO_DATA_FOUND
            For i = 0 To Column – 1
                Select Case ColumnType(i + 1)
                    Case SQL_INTEGER
                        Ret = SQLGetData(hstmt, i + 1, SQL_C_LONG, VarPtr(ValueInt), 4, pcbValue)
                        Debug.Print ValueInt
                    Case SQL_NVARCHAR
                        ValueStr = String$(500, Chr(0))
                        Ret = SQLGetData(hstmt, i + 1, SQL_C_CHAR, ValueStr, 500, pcbValue)
                        Debug.Print ValueStr
                End Select
            Next
    Loop
End Sub

Private Function Fetch(hstmt As Long) As Integer
    Fetch = SQLFetch(hstmt)
End Function

ただしこのやり方は行数×列数の数だけSQLGetDataを呼び出す必要がありますので遅いらしいです。
SQLBindColを使うといいらしいのですが…
追記:SQLBindColを使った方法はこちら

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト /  変更 )

Google フォト

Google アカウントを使ってコメントしています。 ログアウト /  変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト /  変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト /  変更 )

%s と連携中

%d人のブロガーが「いいね」をつけました。