不使用 MFC CDatabase/CRecordset 封裝層,直接呼叫 ODBC 核心 API (SQLAllocEnv、SQLConnect、SQLExecDirect 等) 實現資料庫操作,適用於需要精細控制或非 MFC 專案。
SQLHENV hEnv = SQL_NULL_HENV;
SQLHDBC hDbc = SQL_NULL_HDBC;
SQLRETURN ret;
// 分配環境控制代碼
ret = SQLAllocEnv(&hEnv);
if (ret != SQL_SUCCESS) return FALSE;
// 分配連線控制代碼
ret = SQLAllocConnect(hEnv, &hDbc);
if (ret != SQL_SUCCESS) return FALSE;
// 連線資料來源 (DSN 名稱)
ret = SQLConnect(hDbc, (SQLCHAR*)szDSN, SQL_NTS, NULL, 0, NULL, 0);
if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) {
// 連線成功
}
SQLHSTMT hStmt;
SQLAllocHandle(SQL_HANDLE_STMT, hDbc, &hStmt);
CString strSQL = "SELECT NID, ARIQI, NJINE, ASHUOMING ... FROM HHZhiChu WHERE NID = ?";
// 參數化查詢建議使用 SQLBindParameter + SQLExecute
// 簡易版直接拼裝字串:
strSQL.Format(_T("SELECT ... FROM HHZhiChu WHERE NID=%u"), nID);
ret = SQLExecDirect(hStmt, (SQLCHAR*)(LPCTSTR)strSQL, SQL_NTS);
if (ret == SQL_SUCCESS) {
// 綁定欄位至變數
SQLBindCol(hStmt, 1, SQL_C_SLONG, &dbData.m_NID, 0, &cb);
SQLBindCol(hStmt, 2, SQL_C_TIMESTAMP, &dbData.m_ARIQI, 0, &cb);
SQLBindCol(hStmt, 3, SQL_C_DOUBLE, &dbData.m_NJINE, 0, &cb);
SQLBindCol(hStmt, 4, SQL_C_CHAR, dbData.m_ASHUOMING, SIZE, &cb);
// ... 其他欄位 ...
// 擷取單筆資料
if (SQLFetch(hStmt) == SQL_SUCCESS) {
// dbData 已填入資料,可直接使用
}
}
SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
if (bConnected) {
SQLDisconnect(hDbc);
SQLFreeHandle(SQL_HANDLE_DBC, hDbc); hDbc = SQL_NULL_HDBC;
}
if (hEnv) {
SQLFreeHandle(SQL_HANDLE_ENV, hEnv); hEnv = SQL_NULL_HENV;
}
// 可選:移除臨時 DSN
SQLConfigDataSource(NULL, ODBC_REMOVE_DSN, driver, szAttr);
| 功能 | API 呼叫範例 |
|---|---|
| 建立資料庫 | SQLConfigDataSource(NULL, ODBC_ADD_DSN, "Microsoft Access Driver (*.mdb)", "CREATE_DB=c:\\db.mdb General") |
| 壓縮資料庫 | SQLConfigDataSource(NULL, ODBC_ADD_DSN, driver, "COMPACT_DB=src.mdb dest.mdb General") |
| 取得資料庫名稱 | SQLGetInfo(hDbc, SQL_DATABASE_NAME, szName, MAX_LEN, &len) |
| 新增 DSN | SQLConfigDataSource(NULL, ODBC_ADD_DSN, driver, "DSN=Name;DBQ=path.mdb") |
| 刪除 DSN | SQLConfigDataSource(NULL, ODBC_REMOVE_DSN, driver, "DSN=Name") |
| 列舉系統 DSN | SQLDataSources(hEnv, SQL_FETCH_FIRST/NEXT, szDSN, MAX, &len1, szDesc, MAX, &len2) |
SQLCHAR szSqlState[6], szMsg[256];
SQLINTEGER nErr;
SQLSMALLINT nMsgLen;
SQLError(hEnv, hDbc, hStmt, szSqlState, &nErr, szMsg, 255, &nMsgLen);
// szSqlState 為標準 SQLSTATE 代碼 (如 08001 連線失敗)
建議: 新專案優先考慮 ODBC 3.5+ 模式 (SQLAllocHandle取代SQLAllocEnv/Connect)、參數化查詢 (SQLBindParameter + SQLExecute) 防止 SQL 注入、連線池管理。本文展示核心流程以利理解底層機制。