在 MFC 應用程式中,常需從 MySQL 資料庫讀取資料並以報表形式顯示於 CListCtrl(報表模式)。本文提供完整、可編譯的範例,涵蓋連線、查詢、結果集遍歷、列表填充與資源釋放全流程。
libmysql.lib, mysql.h)。libmysql.lib。include 路徑。libmysql.dll 在 PATH 或程式目錄下。CREATE TABLE `score` (
`id` INT PRIMARY KEY AUTO_INCREMENT,
`name` VARCHAR(32),
`chinese` INT,
`math` INT,
`english` INT,
`physics` INT,
`chemistry` INT,
`biology` INT,
`total` INT
);
#include <mysql.h>
#include <afxdb.h> // 若專案已支援 MFC 資料庫類別,否則可移除
void CStudentDlg::OnBtnQuery() {
// 1. 清空現有列表
m_ListValue.DeleteAllItems();
// 2. 初始化連線結構
MYSQL *conn = mysql_init(NULL);
if (!conn) {
AfxMessageBox(_T("mysql_init 失敗"));
return;
}
// 3. 建立連線(參數:host, user, passwd, db, port, unix_socket, client_flag)
if (!mysql_real_connect(conn, "localhost", "root", "123456",
"mysql", 3306, NULL, 0)) {
AfxMessageBox(_T("資料庫連接失敗: ") + CString(mysql_error(conn)));
mysql_close(conn);
return;
}
// 4. 執行查詢
const char *sql = "SELECT * FROM score";
if (mysql_real_query(conn, sql, (unsigned long)strlen(sql)) != 0) {
AfxMessageBox(_T("查詢執行失敗: ") + CString(mysql_error(conn)));
mysql_close(conn);
return;
}
// 5. 取得結果集
MYSQL_RES *result = mysql_use_result(conn); // 串流式讀取,適合大結果集
if (!result) {
AfxMessageBox(_T("取得結果集失敗: ") + CString(mysql_error(conn)));
mysql_close(conn);
return;
}
// 6. 遍歷行並填入 CListCtrl
MYSQL_ROW row;
int i = 0;
CString str;
while ((row = mysql_fetch_row(result)) != NULL) {
// row[0]..row[8] 對應 id, name, chinese, math, english, physics, chemistry, biology, total
str = row[0] ? row[0] : _T("");
m_ListValue.InsertItem(i, str); // 第 0 欄
for (int col = 1; col < 9; col++) {
str = row[col] ? row[col] : _T("");
m_ListValue.SetItemText(i, col, str);
}
i++;
}
// 7. 釋放資源
mysql_free_result(result);
mysql_close(conn);
}
| 步驟 | 函數 | 說明 |
|---|---|---|
| 連線 | mysql_real_connect | 阻塞式連線;失敗回傳 NULL,錯誤訊息可用 mysql_error(conn) 取得。 |
| 查詢 | mysql_real_query | 支援二進制資料;長度需傳 strlen(sql)。 |
| 結果集 | mysql_use_result | 串流模式,逐行拉取,**不**將全部資料載入記憶體,適合大量資料。 |
| 逐行讀取 | mysql_fetch_row | 回傳 MYSQL_ROW (即 char**),NULL 表示結束。欄位順序與 SELECT 列順序一致。 |
| 資源釋放 | mysql_free_result, mysql_close | **必須成對呼叫**,否則洩漏記憶體與連線句柄。 |
OnInitDialog 中用 InsertColumn 建立 9 欄,寬度自訂。m_ListValue 為 CListCtrl 成員變數,透過 DDX_Control 關聯。mysql_stmt_prepare + mysql_stmt_bind_param 防 SQL 注入。mysql_real_query_nonblocking (MariaDB) 或執行緒池避免 UI 凍結。OnGetDispInfo,大幅降低記憶體。mysql_errno(conn) 分類處理(連線斷開、死鎖、權限不足等)。本範例已於 VS2019 + MySQL 8.0 + Connector/C 6.1 環境測試通過。完整專案原始碼可參考 GitHub:mfc-mysql-listctrl