首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 組合語言

組合語言 ODBC 進階:結果集擷取與 SQLBindCol/SQLFetch 完整解析

     編輯:組合語言

前言

執行 SQL 查詢後,如何高效、正確地處理回傳的結果集,是 ODBC 程式設計的關鍵。本文深入解析 SQLNumResultCols、SQLBindCol、SQLFetch、SQLCloseCursor 的運作機制與實戰技巧,並以經典的「經緯度」比喻幫助理解游標與欄位綁定的關係。

結果集處理四步驟

  1. 確認結果集存在:SQLNumResultCols
  2. 綁定欄位到變數:SQLBindCol
  3. 逐列擷取資料:SQLFetch
  4. 關閉游標釋放資源:SQLCloseCursor

關鍵 API 詳細解析

1. SQLNumResultCols — 確認結果集

SQLNumResultCols proto StatementHandle:DWORD, pNumCols:DWORD
; 回傳:pNumCols 指向的 DWORD = 欄位數
; 若為 0 → 無結果集(如 INSERT/UPDATE/DDL)

適用場景:使用者動態輸入 SQL 陳述式,無法預知是否會傳回資料列。

2. SQLBindCol — 欄位綁定

SQLBindCol proto StatementHandle:DWORD,
    ColumnNumber:DWORD,      ; 1-based,0 為書籤欄
    TargetType:DWORD,        ; SQL_C_CHAR, SQL_C_LONG, SQL_C_DOUBLE 等
    TargetValuePtr:DWORD,    ; 緩衝區位址
    BufferLength:DWORD,      ; 緩衝區長度(位元組)
    pStrLenOrIndPtr:DWORD    ; 實際資料長度/指標變數位址

範例:綁定第 1 欄字串到 21 位元組緩衝區

.data?
buffer db 21 dup(?)
DataLength dd ?
.code
invoke SQLBindCol, hStmt, 1, SQL_C_CHAR, addr buffer, 21, addr DataLength

呼叫 SQLFetch 後,buffer 含資料,DataLength 含實際長度(不含結束符)。

3. SQLFetch — 逐列擷取

SQLFetch proto StatementHandle:DWORD
; 回傳:SQL_SUCCESS / SQL_SUCCESS_WITH_INFO / SQL_NO_DATA(=100)

游標機制:

  • 結果集建立時,游標指向第一列之前。
  • 每次 SQLFetch 將游標前移一列,並將綁定欄位資料填入緩衝區。
  • 無更多列時回傳 SQL_NO_DATA,應跳出迴圈。

4. SQLCloseCursor — 清理資源

invoke SQLCloseCursor, hStmt
invoke SQLFreeHandle, SQL_HANDLE_STMT, hStmt

務必在處理完結果集後呼叫,釋放鎖定與控制代碼。

完整擷取迴圈範例

.data?
buffer db 21 dup(?)
DataLength dd ?
row dd 0
.code
; 綁定欄位
invoke SQLBindCol, hStmt, 1, SQL_C_CHAR, addr buffer, 21, addr DataLength
; 可重複綁定多欄:第 2、3 欄...

mov row, 0
.fetch_loop:
    ; 選擇性清空緩衝區(或改用 DataLength 判斷)
    mov byte ptr [buffer], 0
    invoke SQLFetch, hStmt
    .if ax == SQL_SUCCESS || ax == SQL_SUCCESS_WITH_INFO
        ; 處理 buffer 中的資料
        ; 例如送入 ListView、列印、寫檔...
        inc row
        jmp .fetch_loop
    .endif
    ; SQL_NO_DATA 或錯誤 → 結束
    invoke SQLCloseCursor, hStmt

進階技巧與注意事項

主題說明
書籤欄ColumnNumber=0 為書籤,可用於隨機存取,需驅動程式支援。
資料長度變數優先檢查 pStrLenOrIndPtr 指向的值,而非假設緩衝區以 0 結尾(二進位資料可能含 0)。
緩衝區大小預留足夠空間(含結束符),過小會導致截斷與 SQL_SUCCESS_WITH_INFO + SQLSTATE 01004。
多結果集若預存程序傳回多結果集,需呼叫 SQLMoreResults 切換。
游標類型預設為前進唯讀;需捲動游標時,分配 Stmt 前設定 SQL_ATTR_CURSOR_TYPE。

經典比喻:經緯度與地球

「還記得地球的經緯嗎?我們通過 SQLBindCol 來定位經度(欄),用游標來定義緯度(列),用 SQLFetch 來獲得座標,而結果集就是地球。」(譯者原文)

這個比喻精準捕捉了「欄位綁定=固定經度」、「游標移動=改變緯度」的正交關係。

錯誤處理模式

invoke SQLFetch, hStmt
.if ax == SQL_ERROR
    ; 呼叫 SQLError 取得詳細錯誤資訊
    invoke SQLError, hEnv, hConn, hStmt, addr SqlState, addr NativeError, addr ErrMsg, sizeof ErrMsg, addr TextLen
    ; 顯示或記錄錯誤
.elseif ax == SQL_NO_DATA
    ; 正常結束
.else
    ; 成功取得一列
.endif

總結

掌握 SQLBindCol + SQLFetch 迴圈模式,是 ODBC 程式設計的核心技能。關鍵在於:正確綁定型別與緩衡區、善用長度指標變數、嚴格檢查回傳碼、完整釋放資源。本文提供的範本可直接套用於實務專案,並能延伸支援捲動游標、多結果集、非同步執行等進階功能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved