欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

MySQL中C接口的實(shí)現(xiàn)

 更新時(shí)間:2025年09月28日 10:21:57   作者:綿陽(yáng)的腦內(nèi)SSD  
本節(jié)內(nèi)容介紹使用C/C++訪問(wèn)數(shù)據(jù)庫(kù),?包括對(duì)數(shù)據(jù)庫(kù)的增刪查改操作,主要是學(xué)習(xí)一些接口的調(diào)用,具有一定的參考價(jià)值,感興趣的可以了解一下

前言:本節(jié)內(nèi)容介紹使用C/C++訪問(wèn)數(shù)據(jù)庫(kù), 包括對(duì)數(shù)據(jù)庫(kù)的增刪查改操作。 主要是學(xué)習(xí)一些接口的調(diào)用, 廢話不多說(shuō), 開(kāi)始我們的學(xué)習(xí)吧!

ps:本節(jié)內(nèi)容比較容易, 友友們放心觀看哦!

準(zhǔn)備mysql庫(kù)

其實(shí)我們?cè)L問(wèn)mysql不只是使用命令行進(jìn)行訪問(wèn), 我們未來(lái)訪問(wèn)數(shù)據(jù)庫(kù)一定是一個(gè)程序?qū)?shù)據(jù)庫(kù)進(jìn)行訪問(wèn), 而程序其實(shí)就是代碼。所以未來(lái)我們可以使用代碼來(lái)訪問(wèn)數(shù)據(jù)庫(kù), 這里我們使用C/C++代碼對(duì)數(shù)據(jù)庫(kù)進(jìn)行訪問(wèn)。

首先我們創(chuàng)建一個(gè)非root級(jí)別用戶和一個(gè)數(shù)據(jù)庫(kù):

然后我們要知道, 我們?cè)L問(wèn)數(shù)據(jù)要有對(duì)應(yīng)的開(kāi)發(fā)包, 這些開(kāi)發(fā)包我們可以直接在apt里面找到下載安裝。

sudo apt install -y libmysqlclient-dev

安裝好了之后我們就能在/usr/include/路徑下面看到mysql目錄

這個(gè) 里面包含著我們需要的文件, 像什么mysql.h就是我們所需要的。

然后在/usr/lib/x86_64-linux-gnu里面也有我們的mysql的連接庫(kù):

使用mysql庫(kù)

編譯文件

然后使用庫(kù),系統(tǒng)會(huì)默認(rèn)搜索的路徑是/lib/include路徑, 然后我們要使用的mysql.h頭文件在/lib/include西面的/mysql目錄下面, 所以我們包含頭文件要使用mysql/mysql.h:

#include<mysql/mysql.h>  

mysql_get_client_info函數(shù)可以打印當(dāng)前mysql的版本信息。 

#include<iostream>
#include<mysql/mysql.h>  
using namespace std;

int main()
{
    cout << "mysql_client version: " << mysql_get_client_info() << endl;       
    return 0;
}

然后編譯可能會(huì)出現(xiàn)問(wèn)題:

這是因?yàn)橐驗(yàn)槲覀兙幾g的時(shí)候系統(tǒng)找不到鏈接的庫(kù), 所以需要我們使用-l指令指定路徑:

 -lmysqlclient;

然后就能運(yùn)行成功了:

官方API文檔

然后就是我們要對(duì)數(shù)據(jù)庫(kù)進(jìn)行增刪查改,我們可以去mysql的官方文檔進(jìn)行查看對(duì)應(yīng)的資料

先進(jìn)入官方網(wǎng)站,點(diǎn)擊文檔:

然后下滑找到并點(diǎn)擊C API:

然后點(diǎn)擊function就能看到我們常用的一些函數(shù)了:

知道了這些之后, 下面開(kāi)始學(xué)習(xí)增刪查改:

對(duì)象的創(chuàng)建和關(guān)閉

#include<iostream>
#include<mysql/mysql.h>  
using namespace std;

int main()
{
    MYSQL* my = mysql_init(nullptr);
    if (nullptr)
    {
        cerr << "init MySQL error" << endl;
        return 1;
    }
    
    mysql_close(my);
    return 0;
}

這里面的MYSQL類型就類似于我們C語(yǔ)言里面的FILE類型, 都是一個(gè)句柄。如果成功了就是返回一個(gè)非空的值, 就代表我們獲得了拒柄。 

既然獲得句柄, 那么最后情況下還要關(guān)閉數(shù)據(jù)庫(kù), 釋放一系列資源。 使用mysql_close函數(shù), 就類似于我們關(guān)閉文件的操作。

鏈接數(shù)據(jù)庫(kù)

在官方文檔中給出的mysql鏈接函數(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)

其中的第一個(gè)參數(shù)就是我們剛剛獲取的句柄。 然后第二個(gè)參數(shù)就是登錄的mysql所在的ip地址, 這里我們采用本地環(huán)回;  第三個(gè)參數(shù)就是就是使用的用戶名; 第四個(gè)參數(shù)就是對(duì)應(yīng)用戶的密碼; 第五個(gè)參數(shù)就是數(shù)據(jù)庫(kù)的名稱;第六個(gè)參數(shù)就是端口號(hào);剩下的參數(shù)默認(rèn)即可。返回值就是MYSQL*也就是句柄, 如果是nullptr就是連接失敗。

#include<iostream>
#include<mysql/mysql.h>  
#include<string>
using namespace std;
const string host = "localhost";
const string user = "mian_yang";
const string passwd = "XXXXXXXXXXXXXXXX";
const string db = "school_book_manage";
const unsigned int port = 3306;

int main()
{
    MYSQL* my = mysql_init(nullptr);
    if (nullptr)
    {
        cerr << "init MySQL error" << endl;
        return 1;
    }
    //

    if (mysql_real_connect(my, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0) == nullptr)
    {
        cerr << "connect error" << endl;
        return 0;
    }
    //
    cout << "connect success" << endl;

    mysql_close(my);
    return 0;
}

然后我們編譯一下運(yùn)行一下:

下達(dá)sql指令

然后我們就可以使用函數(shù)下達(dá)sql指令, 在官方文檔中給出的函數(shù)如下:        

int
mysql_query(MYSQL *mysql,
            const char *stmt_str)

其中第一個(gè)參數(shù)就是我們的句柄。 然后第二個(gè)參數(shù)就是我們要下達(dá)的指令。返回值如果為零就執(zhí)行成功了, 如果不為零, 就執(zhí)行失敗了。然后下面是代碼:

#include<iostream>
#include<mysql/mysql.h>  
#include<string>
using namespace std;
const string host = "localhost";
const string user = "mian_yang";
const string passwd = "MYhylk563_al36huz.6";
const string db = "school_book_manage";
const unsigned int port = 3306;



int main()
{
    MYSQL* my = mysql_init(nullptr);
    if (nullptr)
    {
        cerr << "init MySQL error" << endl;
        return 1;
    }
    //

    if (mysql_real_connect(my, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0) == nullptr)
    {
        cerr << "connect error" << endl;
        return 0;
    }
    //
    cout << "connect success" << endl;


    string sql;
    while (true)
    {
        cout << ">>";
        if (!getline(cin, sql) || sql == "quit") break;
        int n = mysql_query(my, sql.c_str());
        if (n == 0) 
        {
            cout << sql << "  success "<<endl;
        }
        else cout << sql << "  error" << endl;
    }

    mysql_close(my);
    return 0;
}

運(yùn)行的時(shí)候我們就來(lái)測(cè)驗(yàn)一下進(jìn)行插入:

然后也可以看到我們的sql語(yǔ)句執(zhí)行成功了!

現(xiàn)在我們插入一下李四, 插入中文, 我們查看一下結(jié)果:

我們會(huì)看到李四被正常的插入進(jìn)去了。 這里博主要說(shuō)的是, 對(duì)于mysql8.0來(lái)說(shuō), 博主使用的是mysql8.0, 這里使用插入函數(shù)插入中文會(huì)正常插入。 但是如果是5.7版本的mysql, 那么這里如果插入中文插入的就是一堆亂碼。所有的亂碼問(wèn)題都是客戶端和服務(wù)器雙方?jīng)]有形成編碼一致。比如說(shuō)服務(wù)端使用utf8, 而客戶端使用的是其他的編碼方式。編碼不一致,那么我編碼使用的是utf8, 你解碼使用的是其他的方式。 那么就亂碼了。

這里我們的8.0數(shù)據(jù)庫(kù), 表編碼都是utf8mb4的,說(shuō)明我們的客戶端也是utf8mb4的。如果我們?cè)O(shè)置成其他的再插入就是一堆亂碼, 這里試驗(yàn)一下:使用mysql_set_character_set函數(shù)設(shè)置解碼方式:

    mysql_set_character_set(my, "latin1");

插入成功: 

可以看到, 解碼出來(lái)就是一堆亂碼。

現(xiàn)在問(wèn)題來(lái)了, 我們上面的插入試驗(yàn)成功了, select語(yǔ)句呢? 我們的select語(yǔ)句是查, 要打印給我們一系列信息。 這里博主可以說(shuō)一下實(shí)驗(yàn)結(jié)果, 結(jié)果是執(zhí)行成功, 但是沒(méi)有打印結(jié)果。 其他的像update, delete操作都能執(zhí)行成功。 只有select 雖然執(zhí)行成功但是沒(méi)有給我們顯示信息, 這是因?yàn)槠渌膕ql語(yǔ)句都只需要執(zhí)行成功即可, 但是select語(yǔ)句還要進(jìn)行后續(xù)的處理, 比如打印。 所以select語(yǔ)句怎么處理呢? 

select語(yǔ)句

我們查出來(lái)的是一種表結(jié)構(gòu)。 如果我們查出來(lái)有四條數(shù)據(jù), 那么就有四行。 如果我們查出來(lái)的表有四列屬性, 那么查出來(lái)就有四列。 我們要知道我們要查的是一些數(shù)據(jù)。 那么這些數(shù)據(jù)在mysql內(nèi)部就一定要有對(duì)應(yīng)的內(nèi)存空間保存這個(gè)數(shù)據(jù)。 mysql將所有的數(shù)據(jù)讀取出來(lái)的時(shí)候全部都當(dāng)作字符串了。 然后有一個(gè)MYSQL_RES對(duì)象,MYSQL_RES對(duì)象就是將這些數(shù)據(jù)進(jìn)行整合一下。 我們可以把MYSQL_RES對(duì)象看成一個(gè)數(shù)組的指針, 這個(gè)數(shù)組里面存儲(chǔ)的數(shù)據(jù)類型是char**類型。 數(shù)組的大小表示一共有多少條記錄。 

然后這些元素都指向一個(gè)char*的數(shù)組:

這個(gè)char*元素指向的就是我們的表結(jié)構(gòu)里面的屬性元素。 所以未來(lái)我們就可以把MYSQL_RES堪稱一個(gè)char** XXX[]數(shù)組。

所以, 這個(gè)MYSQL_RES其實(shí)就是我們使用select語(yǔ)句之后返回的結(jié)果, 這個(gè)結(jié)果的集合就在MYSQL_RES對(duì)象中。 未來(lái)我們想要去除其中的對(duì)象, 我們需要先獲取這個(gè)結(jié)果集里面的行, 里面的列:

MYSQL_RES *
mysql_store_result(MYSQL *mysql); //獲得結(jié)果集
uint64_t
mysql_num_rows(MYSQL_RES *result); //獲取行
unsigned int
mysql_num_fields(MYSQL_RES *result); //獲取列

為了更好的遍歷, mysql提供了一種數(shù)據(jù)結(jié)構(gòu)MYSQL_ROW, 方便我們更好的遍歷, 以后我們就可以直接把這個(gè)RES結(jié)果集當(dāng)成一個(gè)二維數(shù)組來(lái)使用。這個(gè)MYSQL_ROW就相當(dāng)于迭代器, 我們每次調(diào)用, 它都可以自動(dòng)加。

MYSQL_ROW
mysql_fetch_row(MYSQL_RES *result);

然后我們不僅有數(shù)據(jù), 還有我們的列名(列屬性)所以我們就可以獲取一下列名:

MYSQL_FIELD *
mysql_fetch_fields(MYSQL_RES *result)

這個(gè)函數(shù)的返回值是一個(gè)結(jié)構(gòu)里, 這個(gè)結(jié)構(gòu)體里面有著列名稱、取別名后的原生列名稱、 屬于哪個(gè)表、屬于哪個(gè)數(shù)據(jù)庫(kù)等等:

未來(lái)我們想要的就是這個(gè)name字段。 我們?nèi)缓缶涂梢韵虮闅v數(shù)組一樣遍歷這個(gè)列屬性,打印出來(lái)列屬性。

所以, 下面為全部的代碼:

#include<iostream>
#include<mysql/mysql.h>  
#include<string>
using namespace std;
const string host = "localhost";
const string user = "mian_yang";    
const string passwd = "MYhylk563_al36huz.6";
const string db = "school_book_manage";
const unsigned int port = 3306;



int main()
{
    MYSQL* my = mysql_init(nullptr);
    if (nullptr)
    {
        cerr << "init MySQL error" << endl;
        return 1;
    }
    //

    if (mysql_real_connect(my, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0) == nullptr)
    {
        cerr << "connect error" << endl;
        return 0;
    }
    //
    cout << "connect success" << endl;

    string sql = "select * from user";
    int n = mysql_query(my, sql.c_str());
    if (n == 0) cout << sql << " success" << endl;
    else 
    {
        cerr << sql << " error" << endl;
        return 3;
    }
    //
    MYSQL_RES* res = mysql_store_result(my);
    if (res == nullptr) 
    {
        cerr << "res error" << endl;
        return 4;
    }
    MYSQL_FIELD* fields = mysql_fetch_fields(res);
    my_ulonglong cols = mysql_num_rows(res);
    for (int i = 0; i < cols; i++)
    {
        cout << fields[i].name << "\t";
    }
    cout << endl;   

    my_ulonglong rows = mysql_num_rows(res);
    for (int i = 0; i < rows; i++)
    {
        MYSQL_ROW row = mysql_fetch_row(res);
        for (int j = 0; j < cols; j++)
        {
            cout << row[j] << "\t";
        }
        cout << endl;
    }

    mysql_close(my);
    return 0;
}

 然后打印就打印出來(lái)了:

 對(duì)于MYSQL_RES, 其實(shí)MYSQL_RES就是在內(nèi)存中申請(qǐng)了一大塊內(nèi)存空間, 所以最后我們還要free這塊空間。而上層用戶如果使用free釋放空間就會(huì)造成內(nèi)存泄漏或者使用內(nèi)部的原生指針太麻煩。 所以就提供了一個(gè)接口:

void
mysql_free_result(MYSQL_RES *result)

這個(gè)函數(shù)就是系統(tǒng)提供的釋放我們的結(jié)果集。 

到此這篇關(guān)于MySQL中C接口的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)MySQL C接口內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • MySQL中MIN()函數(shù)的使用教程

    MySQL中MIN()函數(shù)的使用教程

    這篇文章主要介紹了MySQL中MIN()函數(shù)的使用教程,是MySQL入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-05-05
  • MySQL窗口函數(shù)實(shí)現(xiàn)榜單排名

    MySQL窗口函數(shù)實(shí)現(xiàn)榜單排名

    相信大家在日常的開(kāi)發(fā)中經(jīng)常會(huì)碰到榜單類的活動(dòng)需求,本文主要介紹了MySQL窗口函數(shù)實(shí)現(xiàn)榜單排名,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • MySQL操作符(and、or、in、not)的具體使用

    MySQL操作符(and、or、in、not)的具體使用

    本文主要介紹了MySQL操作符(and、or、in、not)的具體使用,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • mysql中異常錯(cuò)誤ERROR:2002的解決方法

    mysql中異常錯(cuò)誤ERROR:2002的解決方法

    最近在啟動(dòng)mysql的時(shí)候發(fā)現(xiàn)mysql報(bào)錯(cuò)了,錯(cuò)誤代碼是2002,通過(guò)查找相關(guān)的資料發(fā)現(xiàn)是var/lib/mysql 的訪問(wèn)權(quán)限問(wèn)題,所以這篇文章主要介紹了mysql中異常錯(cuò)誤ERROR:2002的解決方法,需要的朋友可以參考借鑒,下面來(lái)一起看看吧。
    2017-03-03
  • MySQL實(shí)現(xiàn)免密登錄的三種配置方式

    MySQL實(shí)現(xiàn)免密登錄的三種配置方式

    我們登錄MySQL的時(shí)候有時(shí)候會(huì)忘記root密碼,這時(shí)我們需要免密登錄,所以這篇文章給大家介紹了MySQL免密登錄的三種方式,文章通過(guò)是示例代碼給出了詳細(xì)的配置方案,需要的朋友可以參考下
    2024-03-03
  • 詳解MySQL中Order By排序和filesort排序的原理及實(shí)現(xiàn)

    詳解MySQL中Order By排序和filesort排序的原理及實(shí)現(xiàn)

    這篇文章主要為大家詳細(xì)介紹了MySQL的Order By排序的底層原理與filesort排序,以及排序優(yōu)化手段,文中的示例代碼講解詳細(xì),感興趣的小編可以跟隨小編一起學(xué)習(xí)一下
    2022-08-08
  • MySQL DBA教程:Mysql性能優(yōu)化之緩存參數(shù)優(yōu)化

    MySQL DBA教程:Mysql性能優(yōu)化之緩存參數(shù)優(yōu)化

    在平時(shí)被問(wèn)及最多的問(wèn)題就是關(guān)于 MySQL 數(shù)據(jù)庫(kù)性能優(yōu)化方面的問(wèn)題,所以最近打算寫(xiě)一個(gè)MySQL數(shù)據(jù)庫(kù)性能優(yōu)化方面的系列文章,希望對(duì)初中級(jí) MySQL DBA 以及其他對(duì) MySQL 性能優(yōu)化感興趣的朋友們有所幫助
    2014-03-03
  • MySQL8.0新特性之不可見(jiàn)主鍵的使用

    MySQL8.0新特性之不可見(jiàn)主鍵的使用

    MySQL8.0.30版本引入不可見(jiàn)主鍵,它可以自動(dòng)為沒(méi)有顯式指定主鍵的?InnoDB?表創(chuàng)建一個(gè)不可見(jiàn)的主鍵,本文主要介紹了MySQL8.0新特性之不可見(jiàn)主鍵的使用,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-04-04
  • SQL觸發(fā)器定義與使用

    SQL觸發(fā)器定義與使用

    SQL的觸發(fā)器和存儲(chǔ)過(guò)程一樣,都是嵌入到SQL中的一段程序,是SQL中管理數(shù)據(jù)的有力工具,本文給大家詳細(xì)介紹SQL觸發(fā)器的定義語(yǔ)法知識(shí),感興趣的朋友一起看看吧
    2023-01-01
  • MySQL存儲(chǔ)過(guò)程中使用動(dòng)態(tài)行轉(zhuǎn)列

    MySQL存儲(chǔ)過(guò)程中使用動(dòng)態(tài)行轉(zhuǎn)列

    這篇文章主要為大家介紹了MySQL存儲(chǔ)過(guò)程中使用動(dòng)態(tài)行轉(zhuǎn)列的相關(guān)資料,需要的朋友可以參考下
    2016-01-01

最新評(píng)論