最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

MYSQL訪問之如何使用C/C++連接數(shù)據(jù)庫

 更新時間:2026年05月28日 10:19:54   作者:埃伊蟹黃面  
本文詳細(xì)介紹了使用C/C++訪問MySQL數(shù)據(jù)庫的方法,包括初始化連接、執(zhí)行SQL語句和獲取查詢結(jié)果等內(nèi)容,并強調(diào)了連接池的使用以提高性能和資源利用率,感興趣的朋友一起看看吧

1. 前言

我們已經(jīng)學(xué)習(xí)了在 MySQL 客戶端中直接執(zhí)行 SQL 語句來操作數(shù)據(jù),但真正在應(yīng)用開發(fā)中,我們是通過編程語言來訪問數(shù)據(jù)庫的。比如用C/C++編寫的后端服務(wù),需要在自己的代碼里連接MySQL、執(zhí)行SQL、處理結(jié)果。那么,如何使用C/C++來訪問數(shù)據(jù)庫呢?這就要用到MySQL官方提供的C API庫。

在開始編程之前,我們需要做一些準(zhǔn)備:

創(chuàng)建一個專門用于連接的 MySQL 用戶賬號。為了安全和管理,我們不會在代碼里直接使用 root 賬號。

  • 創(chuàng)建一個測試庫 conn。
  • 創(chuàng)建一個賬號 xay,并賦予它關(guān)于 conn 庫的所有權(quán)限,且只允許本地登錄,執(zhí)行命令:grant all on conn.* to 'xay'@'localhost';

安裝 C/C++ 訪問 MYSQL 所需的開發(fā)庫。例如:在 CentOS 上,可以執(zhí)行 yum install mysql-devel,這會安裝 MYSQL 客戶端的頭文件和動態(tài)鏈接庫。頭文件通暢位于 /usr/include/mysql,庫文件位于 /user/lib64/mysql。

2.核心API接口與應(yīng)用

MySQL的C API設(shè)計得很直觀,整個使用流程就像文件操作一樣:打開文件 -> 操作 -> 關(guān)閉文件。這里的“文件”就是數(shù)據(jù)庫連接,對應(yīng)的“句柄”類型是 MYSQL

2.1 初始化和連接

mysql_init()  

函數(shù)原型:MYSQL *mysql_init(MYSQL *mysql)

功能:初始化一個MYSQL句柄。在使用任何其他MySQL API之前,必須先調(diào)用它來創(chuàng)建和初始化一個連接句柄。

MYSQL *my = mysql_init(nullptr); 這里傳nullptr,它會為你分配并返回一個新的MYSQL對象。

mysql_real_connect()

初始化完畢之后,必須用這個函數(shù)來建立到數(shù)據(jù)庫服務(wù)器的實際連接。

函數(shù)原型:MYSQL *mysql_real_connect(MYSQL *mysql,     const char *host,     const char *user,     const char *passwd,     const char *db,

     unsigned int port,     const char *unix_socket,     unsigned long client_flag)

功能:鏈接數(shù)據(jù)庫    初始化完畢之后,必須先鏈接數(shù)據(jù)庫,在進行后續(xù)操作

參數(shù) mysql:函數(shù)mysql_init的返回值

參數(shù) host:連接的主機的IP/域名

參數(shù) user:登錄的用戶名

參數(shù) password:登錄密碼

參數(shù) db:要連接的數(shù)據(jù)庫名

參數(shù) port:MySQL服務(wù)端口,通常是3306

參數(shù) unix_socket:域間套接字,本地連接時可指定socket文件路徑,否則傳nullptr

參數(shù) client_flag:一般設(shè)置成0

建立好鏈接之后,獲取英文沒有問題,但如果數(shù)據(jù)庫中有中文,查詢結(jié)果可能會是亂碼。這是因為連接的默認(rèn)字符集是latin1。我們可以在連接成功后,立即設(shè)置字符集為 utf8mb4 來解決這個問題。

2.2 執(zhí)行SQL和獲取結(jié)果

mysql_query()

函數(shù)原型:int mysql_query(MYSQL *mysql, const char *q);

功能:下發(fā)并執(zhí)行一條mysql命令

參數(shù) mysql:mysql_init的返回值

參數(shù) q:要執(zhí)行的sql語句,如“select * from table”

返回值:如果執(zhí)行成功,返回0;如果出錯,返回非0

獲取結(jié)果集:區(qū)分場景

SQL 執(zhí)行完后,如果是增、刪、改語句,我們主要關(guān)心操作是否成功,也就是看mysql_query的返回值和受影響的行數(shù)。但如果是查詢語句,我們還需要讀取返回的數(shù)據(jù)表,這就要用到結(jié)果集相關(guān)的函數(shù)。

如何獲取查詢結(jié)果?如果 mysql_query 執(zhí)行查詢語句并返回成功,我們就通過 mysql_store_result來把結(jié)果集從服務(wù)器取到客戶端內(nèi)存中。

函數(shù)原型:MYSQL_RES *mysql_store_result(MYSQL *mysql);

功能:將服務(wù)器返回的整個查詢結(jié)果集存儲到本地。它返回一個 MYSQL_RES 類型的指針,我們可以通過它來解析表格數(shù)據(jù)

這個函數(shù)在內(nèi)部malloc了一片內(nèi)存空間來存儲查詢結(jié)果,我們必須在用完結(jié)果集后,調(diào)用 mysql_free_result(result) 來釋放,否則會造成內(nèi)存泄漏!

解析結(jié)果集

拿到 MYSQL_RES * 后,我們就可以像操作一個二維表一樣來讀取數(shù)據(jù)了。

獲取行數(shù):mysql_num_rows

函數(shù)原型:my_ulonglong mysql_num_rows(MYSQL_RES *res)

功能:返回結(jié)果集的總行數(shù)。

獲取列數(shù):mysql_num_fields

函數(shù)原型:unsigned int mysql_num_fields(MYSQL_RES *res);

功能:返回結(jié)果集的總列數(shù)。

獲取列名(字段頭):mysql_fetch_fields

函數(shù)原型:MYSQL_FIELD *mysql_fetch_fields(MYSQL_RES *res);

功能:返回一個包含所有字段信息的數(shù)組,數(shù)組長度就是列數(shù)。我們可以通過 MYSQL_FIELD 結(jié)構(gòu)體中的 name 成員來獲取每一列的列名。

MYSQL_FIELD 常用成員屬性:

成員名類型說明
namechar *列名(字段名),如 "id""username",這是我們最常用的
tablechar *該列所屬的表名(如果查詢涉及多表,這個很有用)
dbchar *該列所屬的數(shù)據(jù)庫名
catalogchar *目錄名,通??偸?nbsp;"def"
defchar *該列的默認(rèn)值(如果沒有默認(rèn)值則為NULL)
lengthunsigned long該列定義的最大長度(不是實際數(shù)據(jù)的長度),比如 varchar(100) 就是 100
typeenum enum_field_types該列的MySQL數(shù)據(jù)類型,例如 MYSQL_TYPE_LONG(整數(shù))、MYSQL_TYPE_VAR_STRING(變長字符串)等,可以用于判斷某列是數(shù)字還是字符串
flagsunsigned int列的標(biāo)志位,一個位掩碼,可以組合多種標(biāo)志,常見的有:
• NOT_NULL_FLAG - 字段不能為空
• PRI_KEY_FLAG - 是主鍵的一部分
• UNIQUE_KEY_FLAG - 是唯一鍵的一部分
• AUTO_INCREMENT_FLAG - 是自增字段
• NUM_FLAG - 是數(shù)字類型
等等
charsetnrunsigned int該列的字符集編號

獲取每一行數(shù)據(jù):mysql_fetch_row

函數(shù)原型:MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);

功能:逐行讀取結(jié)果集。每次調(diào)用,它會返回一個指向當(dāng)前行數(shù)據(jù)的 MYSQL_ROW,并把內(nèi)部指針移到下一行。當(dāng)沒有更多行時,返回NULL。

MYSQL_ROW 本質(zhì)上是 char **,你可以把它當(dāng)成一個字符串?dāng)?shù)組,通過下標(biāo) row[0]、row[1]...來訪問該行每一列的值。

2.3 接口的使用

上述的部分接口使用方式如下所示:

// 打印表的字段
MYSQL_FIELD *fields_array = mysql_fetch_fields(res);
for(my_ulonglong i = 0; i < fields; i++)
    std::cout << fields_array[i].name << '\t';
std::cout << std::endl;
my_ulonglong rows = mysql_num_rows(res);
my_ulonglong fields = mysql_num_fields(res);
std::cout << "行: " << rows << std::endl;
std::cout << "列: " << fields << std::endl;
for(my_ulonglong i = 0; i < rows; i++)
{
    MYSQL_ROW data = mysql_fetch_row(res);
    for(my_ulonglong j = 0; j < fields; j++)
    {
        std::cout << data[j] << "\t";
    }
    std::cout << std::endl;
}

運行結(jié)果:

mysql_real_connect() success
mysql_query success
行: 5
列: 3
id    name    blance
1    張三    100.00
2    李四    200.00
3    王五    300.00
4    趙六    400.00
6    南宮    600.00

上面的例子是單個連接的簡單使用。但在真實的Web服務(wù)器中,如果每個用戶請求都去新建和銷毀一個數(shù)據(jù)庫連接,開銷會非常大,且無法控制并發(fā)連接數(shù)。因此,實際應(yīng)用中通常使用 連接池。

連接池 本質(zhì)上是一個管理數(shù)據(jù)庫連接的容器,內(nèi)部包含一個線程池和一組預(yù)先創(chuàng)建好的MySQL連接對象。當(dāng)業(yè)務(wù)線程需要訪問數(shù)據(jù)庫時,就從池中“借用”一個空閑連接,用完后再“歸還”給池,而不是直接關(guān)閉。這樣大大提高了性能和資源利用率。

3. 結(jié)尾

一個用戶邏輯是如何執(zhí)行的?(以注冊和登錄為例)

結(jié)合我們上面講到的C/C++訪問數(shù)據(jù)庫技術(shù),我們來梳理一下用戶注冊和登錄的后臺流程。注意,網(wǎng)站服務(wù)器并不是直接裸露地與數(shù)據(jù)庫交互,它們之間通常有一層用編程語言實現(xiàn)的“中間件”或后端服務(wù)。

注冊流程:

  1. 用戶向網(wǎng)站A發(fā)起注冊請求。
  2. 網(wǎng)站A的 Web 服務(wù)器收到請求,并返回一個注冊頁面。
  3. 用戶填寫用戶名、密碼等信息并點擊提交。
  4. 網(wǎng)站 A 的后端服務(wù)(可能由 C/C++/Java/Go 等編寫)接收到用戶提交的數(shù)據(jù),提取出賬號、密碼等參數(shù)。
  5. 后端服務(wù)對密碼進行加密處理(出于安全考慮,絕不能明文存儲)。
  6. 后端服務(wù)將注冊邏輯構(gòu)建成一條SQL語句,如 insert into user ...。
  7. 這條SQL被下發(fā)給“中間件”(負(fù)責(zé)負(fù)載均衡、分庫分表等)。中間件決定將數(shù)據(jù)寫入到哪一個具體的數(shù)據(jù)庫實例。
  8. 在這一步,中間件或最終執(zhí)行SQL的后臺線程,會使用我們上面講的 mysql_init、mysql_real_connect 等API,從連接池中獲取連接,執(zhí)行insert語句。
  9. 數(shù)據(jù)庫操作成功后,結(jié)果一層層返回,最終網(wǎng)站A告訴用戶“注冊成功”。同時,多個數(shù)據(jù)庫節(jié)點間會進行數(shù)據(jù)同步,保證數(shù)據(jù)一致性。

登錄流程:

  1. 用戶向網(wǎng)站A發(fā)起登錄請求,獲得登錄頁面。
  2. 用戶輸入賬號、密碼并提交。
  3. 網(wǎng)站A后端服務(wù)接收到請求,提取參數(shù)。
  4. 后端服務(wù)構(gòu)建一條查詢SQL,如 select user_id, password from user where username='...'。
  5. 通過中間件路由,SQL最終到達具體的數(shù)據(jù)庫。
  6. 在這一步,后臺程序再次通過C/C++等語言的API,從連接池獲取連接,執(zhí)行select語句,并通過mysql_store_result和mysql_fetch_row獲取查詢結(jié)果。
  7. 后臺程序?qū)⒉榈降募用苊艽a與用戶輸入密碼的加密結(jié)果進行比對。
  8. 如果匹配,則為該用戶生成一個會話憑證(Session),并返回登錄成功;否則,返回賬號或密碼錯誤。

通過C/C++的API,我們就打通了應(yīng)用程序與數(shù)據(jù)存儲之間的橋梁,讓死的數(shù)據(jù)能被靈活地用于活的應(yīng)用邏輯中。

到此這篇關(guān)于MYSQL訪問之如何使用C/C++連接數(shù)據(jù)庫的文章就介紹到這了,更多相關(guān)mysql使用C/C++連接數(shù)據(jù)庫內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

铜陵市| 陇川县| 晋州市| 化州市| 玉山县| 哈尔滨市| 红河县| 贵州省| 阜南县| 沁水县| 孝昌县| 财经| 民县| 永平县| 浑源县| 阿鲁科尔沁旗| 襄樊市| 平顶山市| 蕉岭县| 深圳市| 柳江县| 利川市| 滁州市| 平山县| 龙陵县| 永寿县| 临沭县| 扶风县| 海宁市| 长武县| 龙游县| 郧西县| 田阳县| 甘德县| 安溪县| 华容县| 乡城县| 阿坝| 塔城市| 绿春县| 永靖县|