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

Visual C++ ODBC 數據庫編程實戰:MFC 類封裝、CRUD 操作與 SQL 直執行

     編輯:關於C語言

ODBC:統一數據訪問標準

ODBC (Open Database Connectivity) 通過驅動程序屏蔽底層 DBMS 差異,提供統一 C API。MFC 在此基礎上封裝了三大核心類,極大簡化開發。

一、MFC ODBC 三大核心類

類角色關鍵功能
CDatabase數據源連接OpenEx()、ExecuteSQL()、事務控制
CRecordset記錄集 (結果集)Open()、Requery()、MoveNext()、AddNew/Edit/Delete/Update、篩選/排序
CRecordView數據綁定視圖將記錄集字段自動綁定到對話框控件

二、AppWizard 快速生成框架

  1. File → New → Projects → MFC AppWizard (exe)
  2. 選擇 Database view with file support (讀寫) 或 without file support (只讀)。
  3. 點擊 Data Source 選擇已註冊 ODBC 數據源 (如 Super_ES)。
  4. 選擇操作表 → 完成向導。
  5. 生成的 CRecordset 派生類包含字段映射 (RFX) 代碼。

三、核心操作代碼模式

1. 連接數據庫


CDatabase db;
if (!db.OpenEx(_T("DSN=Super_ES;UID=sa;PWD=;"), CDatabase::noOdbcDialog)) {
    AfxMessageBox(_T("連接失敗"));
    return;
}

2. 查詢記錄 (動態集/快照)


CMyRecordSet rs(&db); // 傳入已打開的 db,復用連接
// 或使用默認連接
// CMyRecordSet rs; rs.m_pDatabase = &db;

rs.m_strFilter = _T("TYPE='電動機'"); // WHERE 條件
rs.m_strSort = _T("VOLTAGE");         // ORDER BY
rs.Open(CRecordset::dynaset);         // 或 snapshot

while (!rs.IsEOF()) {
    // 訪問字段:rs.m_fieldName
    rs.MoveNext();
}
rs.Close();

3. 參數化查詢 (防注入、類型安全)


// 在 Recordset 派生類中聲明參數
CString m_paramType;
double m_paramVoltage;

// DoFieldExchange 中綁定
pFX->SetFieldType(CFieldExchange::param);
RFX_Text(pFX, _T("P1"), m_paramType);
RFX_Double(pFX, _T("P2"), m_paramVoltage);
m_nParams = 2;

// 使用
rs.m_strFilter = _T("TYPE=? AND VOLTAGE=?");
rs.m_paramType = _T("電動機");
rs.m_paramVoltage = 60.0;
rs.Requery();

4. 增加記錄


rs.AddNew();                    // 準備新記錄
rs.m_type = _T("發電機");
rs.m_voltage = 220.0;
// ... 設置其他字段
rs.Update();                    // 寫入數據庫
rs.Requery();                   // 刷新記錄集

5. 修改記錄


rs.Edit();                      // 進入編輯模式
rs.m_type = _T("變壓器");
rs.Update();                    // 提交修改
rs.Requery();

6. 刪除記錄


rs.Delete();                    // 立即刪除,無需 Update
if (!rs.IsEOF()) rs.MoveNext();
else rs.MoveLast();

7. 撤銷操作


rs.Move(AFX_MOVE_REFRESH); // 放棄 AddNew/Edit,恢復原狀態

四、連接復用:多 Recordset 共享 CDatabase


CDatabase db;
db.OpenEx(_T("DSN=Super_ES"), 0);

CRecordSet rs1, rs2;
rs1.m_pDatabase = &db;
rs2.m_pDatabase = &db;

rs1.Open(...);
rs2.Open(...);
// 共享同一物理連接,節省資源

五、SQL 直接執行:DDL/DML 批量操作


BOOL ExecuteSQLAndReport(CDatabase *pdb, const CString& sql) {
    TRY {
        pdb->ExecuteSQL(sql); // 直接執行任意 SQL
        return TRUE;
    }
    CATCH(CDBException, e) {
        CString msg; msg.LoadString(IDS_EXECUTE_SQL_FAILED);
        msg += sql;
        AfxMessageBox(msg);
        return FALSE;
    }
    END_CATCH
}

// 用法
ExecuteSQLAndReport(&db, _T("CREATE TABLE Temp (ID INT PRIMARY KEY, Name VARCHAR(50))"));
ExecuteSQLAndReport(&db, _T("DELETE FROM Logs WHERE Date < '2020-01-01'"));

⚠️ 直接 SQL 破壞 DBMS 無關性,謹慎使用。

六、異常處理:MFC TRY/CATCH 機制


TRY {
    rs.Open(...);
}
CATCH(CDBException, e) {
    CString err; e->GetErrorMessage(err.GetBuffer(255), 255);
    AfxMessageBox(_T("數據庫錯誤: ") + err);
}
END_CATCH

七、避坑指南

  • ✅ OpenEx 檢查返回值,失敗提示用戶。
  • ✅ 使用參數化查詢 (? 佔位符) 防 SQL 注入。
  • ✅ AddNew/Edit 後必須 Update 提交。
  • ✅ 遍歷記錄集檢查 IsEOF/IsBOF。
  • ✅ 多線程各自創建 CDatabase,不可跨線程共享。
  • ❌ 忘記 Close() 記錄集/數據庫 → 連接洩漏。
  • ❌ 直接拼接 SQL 字符串 → 注入風險。
  • ❌ 假設 ExecuteSQL 返回影響行數 (ODBC 不保證)。

總結

MFC ODBC 類 (CDatabase/CRecordset/CRecordView) 將底層 ODBC API 封裝為直觀的 C++ 接口。掌握連接管理、記錄集打開模式 (dynaset/snapshot)、RFX 字段映射、參數化查詢、CRUD 標準流程、連接復用、直接 SQL 執行,即可高效開發健壯的數據庫應用。異常處理與資源釋放是生產級代碼的必修課。

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