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

VC 開發資料庫基礎之 ADO 篇 (2):Connection/Command/Recordset 核心操作全解析

     編輯:VC 教學

三大核心物件操作模式

ADO 物件模型核心:**Connection** (連接) → **Command/Recordset** (執行/結果)。本文詳細解析三種執行 SQL 方式、Recordset 遍歷更新、資源管理。

一、Connection::Execute 三大用法

_variant_t vRecordsAffected;
_RecordsetPtr pRs;

// 1. DDL: 建立資料表
pConn->Execute(L"CREATE TABLE users(ID INT, username TEXT, old INT, birthday DATETIME)",
               &vRecordsAffected, adCmdText);

// 2. DML: 新增記錄
pConn->Execute(L"INSERT INTO users VALUES (1, 'Washington', 25, '1970/1/1')",
               &vRecordsAffected, adCmdText);

// 3. DML: 批次更新
pConn->Execute(L"UPDATE users SET old = old + 1", &vRecordsAffected, adCmdText);

// 4. 查詢返回 Recordset
pRs = pConn->Execute(L"SELECT COUNT(*) FROM users", &vRecordsAffected, adCmdText);
_variant_t vCount = pRs->GetCollect((long)0);  // 取第一欄
pRs->Close();
AfxMessageBox(CString(L"共有 ") + vCount.lVal + L" 條記錄");

二、Command 物件:參數化查詢與預存程序


_CommandPtr pCmd; pCmd.CreateInstance(L"ADODB.Command");
_variant_t vNull; vNull.vt = VT_ERROR; vNull.scode = DISP_E_PARAMNOTFOUND;

pCmd->ActiveConnection = pConn;           // 關鍵:綁定連接
pCmd->CommandText = L"SELECT * FROM users WHERE old > ?";  // 參數化
pCmd->CommandType = adCmdText;

// 建立參數 (可選,若 CommandText 含 ? 需對應)
_ParameterPtr pParm = pCmd->CreateParameter(L"MinAge", adInteger, adParamInput, 4, 18);
pCmd->Parameters->Append(pParm);

_RecordsetPtr pRs = pCmd->Execute(&vNull, &vNull, adCmdText);
// 此時 pRs 只含 old > 18 的記錄

Command 核心優勢:預存程序調用 (`CommandType=adCmdStoredProc`)、參數型別安全、執行計劃重用、防 SQL 注入。

三、Recordset::Open 直接查詢 (最常用)


pRs->Open(L"SELECT * FROM users",
          _variant_t((IDispatch*)pConn, true),  // 連接指標包裝為 VARIANT
          adOpenStatic, adLockOptimistic, adCmdText);

Open 參數詳解

參數常用值說明
CursorTypeadOpenStatic(3)靜態快照,支援書籤/RecordCount,不見他人變更
adOpenDynamic(2)動態,即時同步,開銷大
adOpenKeyset(1)鍵集,見更新不見增刪
adOpenForwardOnly(0)唯讀順向,最快,無 RecordCount
LockTypeadLockOptimistic(3)更新時鎖 (推薦一般編輯)
adLockPessimistic(2)編輯即鎖 (高衝突)
adLockBatchOptimistic(4)批次更新模式
adLockReadOnly(1)唯讀

四、Recordset 遍歷、增刪改完整範例


_variant_t vID, vName, vOld, vBirth;
pRs->Open(L"SELECT * FROM users", _variant_t((IDispatch*)pConn, true),
          adOpenStatic, adLockOptimistic, adCmdText);

// 1. 遍歷輸出
while (!pRs->adoEOF) {
    vID = pRs->GetCollect((long)0);       // 索引 0-based
    vName = pRs->GetCollect(L"username"); // 或欄位名
    vOld = pRs->GetCollect(L"old");
    vBirth = pRs->GetCollect(L"birthday");
    if (vID.vt!=VT_NULL && vName.vt!=VT_NULL && vOld.vt!=VT_NULL && vBirth.vt!=VT_NULL)
        TRACE(L"id:%d, 姓名:%s, 年齡:%d, 生日:%s\n", vID.lVal, (LPCTSTR)_bstr_t(vName), vOld.lVal, (LPCTSTR)_bstr_t(vBirth));
    pRs->MoveNext();
}

// 2. 刪除第一筆
pRs->MoveFirst();
pRs->Delete(adAffectCurrent);

// 3. 新增三筆
for (int i=0; i<3; ++i) {
    pRs->AddNew();
    pRs->PutCollect(L"ID", _variant_t(i+10));
    pRs->PutCollect(L"username", _variant_t(L"葉利欽"));
    pRs->PutCollect(L"old", _variant_t(71));
    pRs->PutCollect(L"birthday", _variant_t(L"1930-3-15"));
}

// 4. 修改第二筆年齡
pRs->Move(1, _variant_t(adBookmarkFirst));  // 從第一筆移動 1 筆
pRs->PutCollect(L"old", _variant_t(45));
pRs->Update();  // 寫入資料庫

五、關閉與資源釋放


pRs->Close();
pConn->Close();
// 智能指標離開作用域自動 Release,亦可手動 pRs = NULL; pConn = NULL;

六、進階預告 (下篇將詳細介紹)

  • **欄位綁定** (`IADORecordBinding`):將 Recordset 欄位直接映射到 C++ 結構體,避免 `GetCollect`/`PutCollect` 字串查找開銷
  • **預存程序參數**:`Command->Parameters` 完整處理 INPUT/OUTPUT/RETURN_VALUE
  • **事務處理**:`Connection->BeginTrans/CommitTrans/RollbackTrans`
  • **二進位/BLOB 處理**:`AppendChunk`/`GetChunk` 或 `Stream` 物件 (圖片/文件存取)
  • **資料形控制項綁定**:`DataGrid`/`MSHFlexGrid` 與 Recordset 無縫綁定

結語

ADO 三大物件操作核心在於:**Connection 管理連接池與事務、Command 封裝參數化邏輯與預存程序、Recordset 提供豐富游標/鎖定模式的結果集操作**。熟練掌握 `Execute`/`Open`/`AddNew/Update/Delete` 與游標鎖定選擇,即可應對 90% 資料庫應用場景。下篇深入綁定、事務、BLOB、預存程序等進階主題。

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