C語(yǔ)言連接MySQL數(shù)據(jù)庫(kù)的完整流程
大家好,最近在學(xué)習(xí)數(shù)據(jù)庫(kù)編程,今天把C 語(yǔ)言連接 MySQL的完整流程整理成一篇超詳細(xì)博客,從庫(kù)文件配置、編譯運(yùn)行,到 API 函數(shù)詳解、完整代碼實(shí)戰(zhàn),一步一步帶你上手,新手也能直接跟著做!
一、前言:為什么用 C 語(yǔ)言連接 MySQL?
MySQL 官方提供了 C 語(yǔ)言原生 API(Connector/C),這是所有語(yǔ)言(Python/Java/PHP)連接 MySQL 的底層基礎(chǔ),性能最高、可控性最強(qiáng),非常適合:
- 后端服務(wù)、嵌入式設(shè)備數(shù)據(jù)庫(kù)操作
- 學(xué)習(xí)數(shù)據(jù)庫(kù)底層交互原理
- 高性能數(shù)據(jù)存取場(chǎng)景
本文完全基于官方庫(kù),不依賴第三方封裝,可直接編譯運(yùn)行。
二、環(huán)境準(zhǔn)備:Connector/C 庫(kù)下載與結(jié)構(gòu)
1. 下載官方庫(kù)
前往 MySQL 官網(wǎng)下載 Connector/C
選擇對(duì)應(yīng)系統(tǒng)版本(Linux 64 位 / Windows),下載后解壓得到兩個(gè)核心目錄:
mysql-connector-c/
├── include/ # 頭文件:所有函數(shù)聲明(mysql.h 等)
└── lib/ # 庫(kù)文件:函數(shù)實(shí)現(xiàn)(.so / .a)
2. 庫(kù)文件作用(必看)
include:告訴編譯器有哪些函數(shù)可以調(diào)用lib:告訴鏈接器函數(shù)的實(shí)現(xiàn)在哪里- 核心庫(kù):
libmysqlclient(動(dòng)態(tài)庫(kù).so/ 靜態(tài)庫(kù).a)
三、第一步:驗(yàn)證庫(kù)引入成功(最簡(jiǎn)測(cè)試)
在寫(xiě)復(fù)雜連接前,先做最小驗(yàn)證,確保環(huán)境配置正確。
1. 測(cè)試代碼(test.c)
#include <stdio.h>
#include <mysql.h> // 必須包含 MySQL 核心頭文件
int main() {
// 獲取客戶端庫(kù)版本
const char* version = mysql_get_client_info();
printf("MySQL Client Version: %s\n", version);
return 0;
}
2. 編譯命令(關(guān)鍵)
gcc -o test test.c -I./include -L./lib -lmysqlclient
參數(shù)說(shuō)明:
-I./include:指定頭文件路徑-L./lib:指定庫(kù)文件路徑-lmysqlclient:鏈接libmysqlclient庫(kù)
3. 運(yùn)行與動(dòng)態(tài)庫(kù)問(wèn)題解決
直接運(yùn)行可能報(bào)錯(cuò):
error while loading shared libraries: libmysqlclient.so.18
原因:系統(tǒng)找不到動(dòng)態(tài)庫(kù),臨時(shí)設(shè)置環(huán)境變量:
export LD_LIBRARY_PATH=./lib ./test
成功輸出:
MySQL Client Version: 6.1.6
庫(kù)引入成功!
四、MySQL C API 核心函數(shù)全解
C 語(yǔ)言操作 MySQL 固定5 步流程:
初始化 → 2. 連接數(shù)據(jù)庫(kù) → 3. 執(zhí)行 SQL → 4. 獲取結(jié)果 → 5. 關(guān)閉連接
1. 初始化:mysql_init
MYSQL* mysql_init(MYSQL* mysql);
- 作用:初始化 MySQL 操作句柄(必須第一步)
- 傳 NULL:自動(dòng)分配空間
- 返回值:成功返回 MYSQL* 句柄,失敗 NULL
示例:
MYSQL* mysql = mysql_init(NULL);
if (mysql == NULL) {
printf("初始化失敗\n");
return 1;
}
2. 建立連接:mysql_real_connect
MYSQL* mysql_real_connect(
MYSQL* mysql,
const char* host, // 主機(jī):localhost / 127.0.0.1
const char* user, // 用戶名:root
const char* passwd, // 密碼
const char* db, // 要連接的數(shù)據(jù)庫(kù)名
unsigned int port, // 端口:3306
const char* unix_socket,// NULL
unsigned long clientflag// 0
);
連接成功后必須設(shè)置字符集,否則中文亂碼:
mysql_set_character_set(mysql, "utf8");
3. 執(zhí)行 SQL:mysql_query
int mysql_query(MYSQL* mysql, const char* sql);
- 作用:下發(fā) SQL 語(yǔ)句(增刪改查都用它)
- 返回 0 成功,非 0 失敗
4. 獲取查詢結(jié)果(SELECT 專用)
mysql_store_result(MYSQL*):把結(jié)果讀到內(nèi)存mysql_num_rows(MYSQL_RES*):獲取結(jié)果行數(shù)mysql_num_fields(MYSQL_RES*):獲取列數(shù)mysql_fetch_fields(MYSQL_RES*):獲取列名mysql_fetch_row(MYSQL_RES*):逐行獲取數(shù)據(jù)
特別注意:MYSQL_RES* 是 malloc 申請(qǐng)的空間,必須手動(dòng)釋放,否則內(nèi)存泄漏!
MYSQL_RES* result = mysql_store_result(mysql); // ... 使用結(jié)果 mysql_free_result(result);
5. 關(guān)閉連接:mysql_close
mysql_close(mysql);
五、完整實(shí)戰(zhàn)代碼:連接 + 查詢 + 打印
直接復(fù)制可用,替換自己的數(shù)據(jù)庫(kù)信息即可運(yùn)行!
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <mysql.h>
int main() {
// 1. 初始化
MYSQL* mysql = mysql_init(NULL);
if (mysql == NULL) {
printf("mysql_init 失敗\n");
return 1;
}
// 2. 連接數(shù)據(jù)庫(kù)(請(qǐng)修改為你的信息)
const char* host = "localhost";
const char* user = "root";
const char* passwd = "123456";
const char* db = "test";
unsigned int port = 3306;
if (mysql_real_connect(mysql, host, user, passwd, db, port, NULL, 0) == NULL) {
printf("連接失敗: %s\n", mysql_error(mysql));
mysql_close(mysql);
return 1;
}
printf("數(shù)據(jù)庫(kù)連接成功 ?\n");
mysql_set_character_set(mysql, "utf8");
// 3. 執(zhí)行查詢 SQL
const char* sql = "SELECT id, name, age FROM student;";
if (mysql_query(mysql, sql) != 0) {
printf("查詢失敗: %s\n", mysql_error(mysql));
mysql_close(mysql);
return 1;
}
// 4. 獲取結(jié)果
MYSQL_RES* res = mysql_store_result(mysql);
if (res == NULL) {
printf("無(wú)結(jié)果或執(zhí)行失敗\n");
mysql_close(mysql);
return 1;
}
// 列數(shù)、列名
int fields = mysql_num_fields(res);
MYSQL_FIELD* field = mysql_fetch_fields(res);
for (int i = 0; i < fields; i++) {
printf("%s\t", field[i].name);
}
printf("\n----------------------------------------\n");
// 逐行打印
MYSQL_ROW row;
while ((row = mysql_fetch_row(res)) != NULL) {
for (int i = 0; i < fields; i++) {
printf("%s\t", row[i] ? row[i] : "NULL");
}
printf("\n");
}
// 5. 釋放資源 + 關(guān)閉
mysql_free_result(res);
mysql_close(mysql);
printf("\n操作完成 ?\n");
return 0;
}
六、編譯運(yùn)行命令
gcc -o mysql_demo mysql_demo.c -I./include -L./lib -lmysqlclient export LD_LIBRARY_PATH=./lib ./mysql_demo
七、常見(jiàn)問(wèn)題匯總(避坑指南)
1.中文亂碼
連接成功后必須加:
mysql_set_character_set(mysql, "utf8");
2.動(dòng)態(tài)庫(kù)找不到
export LD_LIBRARY_PATH=./lib
3.連接失敗 Access denied
檢查 host、user、password、port、db 是否正確
4.內(nèi)存泄漏
MYSQL_RES* 必須 mysql_free_result
八、擴(kuò)展:事務(wù)支持(非常重要)
MySQL C API 原生支持事務(wù):
mysql_autocommit(mysql, 0); // 關(guān)閉自動(dòng)提交 // 執(zhí)行多條 SQL... mysql_commit(mysql); // 提交 // 出錯(cuò)則回滾 mysql_rollback(mysql);
九、總結(jié)
C 語(yǔ)言連接 MySQL 其實(shí)非常簡(jiǎn)單,記住固定流程:初始化 → 連接 → 執(zhí)行 SQL → 獲取結(jié)果 → 釋放關(guān)閉。
到此這篇關(guān)于C語(yǔ)言連接MySQL數(shù)據(jù)庫(kù)的完整流程的文章就介紹到這了,更多相關(guān)C語(yǔ)言連接MySQL數(shù)據(jù)庫(kù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- C語(yǔ)言讀取data.json文件并存入MySQL數(shù)據(jù)庫(kù)小案例(推薦)
- MySQL系列教程之使用C語(yǔ)言來(lái)連接數(shù)據(jù)庫(kù)
- C語(yǔ)言實(shí)現(xiàn)訪問(wèn)及查詢MySQL數(shù)據(jù)庫(kù)的方法
- nodejs和C語(yǔ)言插入mysql數(shù)據(jù)庫(kù)亂碼問(wèn)題的解決方法
- 用C語(yǔ)言操作MySQL數(shù)據(jù)庫(kù)的通用方法
- linux安裝mysql和使用c語(yǔ)言操作數(shù)據(jù)庫(kù)的方法 c語(yǔ)言連接mysql
- c語(yǔ)言連接mysql數(shù)據(jù)庫(kù)的實(shí)現(xiàn)方法
相關(guān)文章
C++深入探究哈希表如何封裝出unordered_set和unordered_map
哈希表是一種根據(jù)關(guān)鍵碼去尋找值的數(shù)據(jù)映射結(jié)構(gòu),該結(jié)構(gòu)通過(guò)把關(guān)鍵碼映射的位置去尋找存放值的地方,說(shuō)起來(lái)可能感覺(jué)有點(diǎn)復(fù)雜,我想我舉個(gè)例子你就會(huì)明白了,最典型的的例子就是字典2022-06-06
樹(shù)存儲(chǔ)結(jié)構(gòu)的幾種表示方法
今天小編就為大家分享一篇關(guān)于樹(shù)存儲(chǔ)結(jié)構(gòu)的幾種表示方法,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-03-03
C語(yǔ)言不用鏈表完成學(xué)生管理系統(tǒng)(完整代碼)
這篇文章主要介紹了C語(yǔ)言不用鏈表完成學(xué)生管理系統(tǒng)(完整代碼),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-04-04
C++?數(shù)據(jù)結(jié)構(gòu)超詳細(xì)講解單鏈表
這篇文章主要介紹了C++數(shù)據(jù)結(jié)構(gòu)之單鏈表,鏈表是由一個(gè)個(gè)結(jié)點(diǎn)鏈結(jié)成的。結(jié)點(diǎn)包括數(shù)據(jù)域和指針域兩部分,數(shù)據(jù)域用來(lái)存儲(chǔ)數(shù)據(jù)元素的信息,指針域用來(lái)存儲(chǔ)下一個(gè)結(jié)點(diǎn)的地址,更詳細(xì)內(nèi)容請(qǐng)需要的小伙伴參考下面文章內(nèi)容2022-03-03
Qt實(shí)現(xiàn)實(shí)時(shí)鼠標(biāo)繪制圖形
這篇文章主要介紹了Qt中QGraphicsView架構(gòu)下如何實(shí)現(xiàn)實(shí)時(shí)鼠標(biāo)繪制圖形,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起動(dòng)手試一試2022-02-02
C語(yǔ)言實(shí)現(xiàn)求解最小公倍數(shù)的算法示例
這篇文章主要為大家介紹了C語(yǔ)言如何實(shí)現(xiàn)求解任意兩個(gè)正整數(shù)的最小公倍數(shù),文中采用了窮舉法和定理法。感興趣的小伙伴快來(lái)跟隨小編一起學(xué)習(xí)學(xué)習(xí)吧2021-12-12

