如何使用C與Mysql進行數(shù)據(jù)交互

  • ArthurSlog

  • SLog-2

  • Year·1

  • Guangzhou·China

  • July 8th 2018


    ArthurSlog

想讓別人拉你一把向拆,你的手在哪废境?別想著拉別人一把杆烁,否則你也會被拖垮。

開發(fā)環(huán)境MacOS

Mac自帶的編譯器沛善,可以直接編譯C語言的代碼坷剧。所以現(xiàn)在,打開你的手機辖试,計時5分鐘辜王,編譯器了解一下

有點常識 最原始的信息一般都是最有效的信息

如果面向百度或者QQ編程,那趁早轉(zhuǎn)行

在Mysql的官網(wǎng)獲取C與Mysql的交互手冊Mysql官方手冊

  • 下面這段話是智商的分水嶺

The MySQL C API is a C-based API that client applications written in C can use to communicate with MySQL Server.Client programs refer to C API header files at compile time and link to a C API library file, libmysqlclient, at link time.

  • 這段話就是實現(xiàn)C與Mysql數(shù)據(jù)交互的關(guān)鍵 如果你看不懂 說明你想的太多 做的太少

提醒:當你想進步的時候罐孝,第一時間打開官方手冊

官方文檔一般都不會考慮菜鳥們的閱讀感受 所以 作為一只??菜鳥 要有點靈性

下面是在MySQL官網(wǎng)找到的一個具體的調(diào)用流程:

  • step1 初始化MySQL客戶端庫呐馆,mysql_library_init()。

  • step2 初始化MySQL對象莲兢,mysql_init()汹来;并連接到服務(wù)器, mysql_real_connect()怒见。

  • step3 發(fā)出SQL語句并處理其結(jié)果俗慈,mysql_eqery()姑宽。

  • step4 關(guān)閉與MySQL服務(wù)器的連接遣耍,mysql_close()。

  • step5 結(jié)束使用MySQL客戶端庫炮车,mysql_library_end()舵变。

下面main.c是完整的C代碼(1分鐘瀏覽一下), 關(guān)鍵是上面提到的五個步驟瘦穆,函數(shù)的用法參考Mysql官方手冊

main.c

#include <stdio.h>
#include <mysql.h>
#include <stdlib.h>

MYSQL mysql;
MYSQL_RES *result;
MYSQL_ROW row;
unsigned int num_fields;
unsigned int i;
const char host_name[] = "localhost";
const char user_name[] = "root";
const char password[] = "888888";
const char db_name[] = "my_db";
unsigned int port_num = 0;
unsigned long CLIENT_MULTI_STATMENTS = 0;

int main(void)
{
    /* step1 int mysql_library_init(int argc, char **argv, char **groups) */
    if (mysql_library_init(0, NULL, NULL))
    {
        fprintf(stderr, "could not initialize MySQL client library\n");
        exit(1);
    }

    /* step2 MYSQL *mysql_init(MYSQL *mysql) */
    mysql_init(&mysql);

    /* step2 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) */
    if (mysql_real_connect(&mysql, host_name, user_name, password,
                           db_name, port_num, NULL, CLIENT_MULTI_STATEMENTS) == NULL)
    {
        printf("mysql_real_connect() failed\n");
        fprintf(stderr, "Failed to connect to database: Error: %s\n", mysql_error(&mysql));
        mysql_close(&mysql);
        exit(1);
    }

    /* step3 int mysql_query(MYSQL *mysql, const char *stmt_str) */
    int status = mysql_query(&mysql, "SELECT * FROM Account"); /* int mysql_query(MYSQL *mysql, const char *stmt_str) */

    if (status)
    {
        printf("Could not execute statement(s)");
        mysql_close(&mysql);
        exit(0);
    }

    /* process each statement result */
    do
    {
        /* did current statement return data? */
        /* MYSQL_RES *mysql_store_result(MYSQL *mysql) */
        result = mysql_store_result(&mysql);
        if (result)
        {
            /* unsigned int mysql_num_fields(MYSQL_RES *result) */
            num_fields = mysql_num_fields(result);
            /* MYSQL_ROW mysql_fetch_row(MYSQL_RES *result) */
            while ((row = mysql_fetch_row(result)))
            {
                unsigned long *lengths;
                lengths = mysql_fetch_lengths(result);
                for (i = 0; i < num_fields; i++)
                {
                    printf("[%.*s] ", (int)lengths[i],
                           row[i] ? row[i] : "NULL");
                }
                printf("\n");
            }
            /* yes; process rows and free the result set */
            /* process_result_set(mysql, result); */
            mysql_free_result(result) /* void mysql_free_result(MYSQL_RES *result) */;
        }
        else /* no result set or error*/
        {
            /* unsigned int mysql_field_count(MYSQL *mysql) */
            if (mysql_field_count(&mysql) == 0)
            {
                printf("lld rows affected\n");
                break;
            }
        }
        /* more results? -1 = no, >0 = error, 0 = yes (keep looping) */
        if ((status = mysql_next_result(&mysql)) > 0) /* int mysql_next_result(MYSQL *mysql) */
        {
            printf("Counld not execute statement\n");
        }
    } while (status == 0);

    /* step4 void mysql_close(MYSQL *mysql) */
    mysql_close(&mysql);

    /* step5 void mysql_library_end(void) */
    mysql_library_end();

    return EXIT_SUCCESS;
}

main.c

    /* step1 int mysql_library_init(int argc, char **argv, char **groups) */
    if (mysql_library_init(0, NULL, NULL))
    {
        fprintf(stderr, "could not initialize MySQL client library\n");
        exit(1);
    }

    /* step2 MYSQL *mysql_init(MYSQL *mysql) */
    mysql_init(&mysql);
    /* step2 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) */
    if (mysql_real_connect(&mysql, host_name, user_name, password,
                           db_name, port_num, NULL, CLIENT_MULTI_STATEMENTS) == NULL)
    {
        printf("mysql_real_connect() failed\n");
        fprintf(stderr, "Failed to connect to database: Error: %s\n", mysql_error(&mysql));
        mysql_close(&mysql);
        exit(1);
    }

    /* step3 int mysql_query(MYSQL *mysql, const char *stmt_str) */
    int status = mysql_query(&mysql, "SELECT * FROM Account"); /* int mysql_query(MYSQL *mysql, const char *stmt_str) */
    if (status)
    {
        printf("Could not execute statement(s)");
        mysql_close(&mysql);
        exit(0);
    }

    /* step4 void mysql_close(MYSQL *mysql) */
    mysql_close(&mysql);

    /* step5 void mysql_library_end(void) */
    mysql_library_end();
  • 這里面涉及到的C語法扛或,google了解一下

  • 上面的代碼走完一個流程就算完了绵咱,但實際情況是需要‘增刪改查’

  • So

main.c

    /* process each statement result */
    do
    {
        /* did current statement return data? */
        /* MYSQL_RES *mysql_store_result(MYSQL *mysql) */
        result = mysql_store_result(&mysql);
        if (result)
        {
            /* unsigned int mysql_num_fields(MYSQL_RES *result) */
            num_fields = mysql_num_fields(result);
            /* MYSQL_ROW mysql_fetch_row(MYSQL_RES *result) */
            while ((row = mysql_fetch_row(result)))
            {
                unsigned long *lengths;
                lengths = mysql_fetch_lengths(result);
                for (i = 0; i < num_fields; i++)
                {
                    printf("[%.*s] ", (int)lengths[i],
                           row[i] ? row[i] : "NULL");
                }
                printf("\n");
            }
            /* yes; process rows and free the result set */
            /* process_result_set(mysql, result); */
            mysql_free_result(result) /* void mysql_free_result(MYSQL_RES *result) */;
        }
        else /* no result set or error*/
        {
            /* unsigned int mysql_field_count(MYSQL *mysql) */
            if (mysql_field_count(&mysql) == 0)
            {
                printf("lld rows affected\n");
                break;
            }
        }
        /* more results? -1 = no, >0 = error, 0 = yes (keep looping) */
        if ((status = mysql_next_result(&mysql)) > 0) /* int mysql_next_result(MYSQL *mysql) */
        {
            printf("Counld not execute statement\n");
        }
    } while (status == 0);
  • 根據(jù)Mysql官方手冊
  • 在代碼間,當一個函數(shù)執(zhí)行后會返回一個結(jié)果熙兔,這個結(jié)果的數(shù)據(jù)結(jié)構(gòu)各不相同悲伶,參考Mysql官方手冊
  • 舉個例子栗子:

main.c

mysql_library_init()
  • 完整的寫法

main.c

int mysql_library_init(int argc, char **argv, char **groups)
  • 第一個 int,代表的就是返回值的數(shù)據(jù)結(jié)構(gòu)
  • 如果要儲存這個函數(shù)執(zhí)行完返回的值住涉,需要聲明一個相同的數(shù)據(jù)結(jié)構(gòu)的對象來保存這個值
  • 舉個栗子:

main.c

int return_mli = null; //聲明一個數(shù)據(jù)結(jié)構(gòu)為int的對象麸锉,并讓reture_mli的值為空
  • 然后你就可以

main.c

int return_mli = null;
return_mli = mysql_library_init(0, NULL, NULL);
  • 此時你就可以判斷函數(shù)的返回值,以確定接下來要執(zhí)行的操作
  • C 語言把任何非零和非空的值假定為 true舆声,把零或 null 假定為 false花沉。

main.c

int return_mli = 0;
return_mli = mysql_library_init(0, NULL, NULL);

if(return_mli)
{
    do something
}
  • 明白了這些柳爽,再次看一下完整的代碼

main.c

#include <stdio.h>
#include <mysql.h>
#include <stdlib.h>

MYSQL mysql;
MYSQL_RES *result;
MYSQL_ROW row;
unsigned int num_fields;
unsigned int i;
const char host_name[] = "localhost";
const char user_name[] = "root";
const char password[] = "888888";
const char db_name[] = "my_db";
unsigned int port_num = 0;
unsigned long CLIENT_MULTI_STATMENTS = 0;

int main(void)
{
    /* step1 int mysql_library_init(int argc, char **argv, char **groups) */
    if (mysql_library_init(0, NULL, NULL))
    {
        fprintf(stderr, "could not initialize MySQL client library\n");
        exit(1);
    }

    /* step2 MYSQL *mysql_init(MYSQL *mysql) */
    mysql_init(&mysql);

    /* step2 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) */
    if (mysql_real_connect(&mysql, host_name, user_name, password,
                           db_name, port_num, NULL, CLIENT_MULTI_STATEMENTS) == NULL)
    {
        printf("mysql_real_connect() failed\n");
        fprintf(stderr, "Failed to connect to database: Error: %s\n", mysql_error(&mysql));
        mysql_close(&mysql);
        exit(1);
    }

    /* step3 int mysql_query(MYSQL *mysql, const char *stmt_str) */
    int status = mysql_query(&mysql, "SELECT * FROM Account"); /* int mysql_query(MYSQL *mysql, const char *stmt_str) */

    if (status)
    {
        printf("Could not execute statement(s)");
        mysql_close(&mysql);
        exit(0);
    }

    /* process each statement result */
    do
    {
        /* did current statement return data? */
        /* MYSQL_RES *mysql_store_result(MYSQL *mysql) */
        result = mysql_store_result(&mysql);
        if (result)
        {
            /* unsigned int mysql_num_fields(MYSQL_RES *result) */
            num_fields = mysql_num_fields(result);
            /* MYSQL_ROW mysql_fetch_row(MYSQL_RES *result) */
            while ((row = mysql_fetch_row(result)))
            {
                unsigned long *lengths;
                lengths = mysql_fetch_lengths(result);
                for (i = 0; i < num_fields; i++)
                {
                    printf("[%.*s] ", (int)lengths[i],
                           row[i] ? row[i] : "NULL");
                }
                printf("\n");
            }
            /* yes; process rows and free the result set */
            /* process_result_set(mysql, result); */
            mysql_free_result(result) /* void mysql_free_result(MYSQL_RES *result) */;
        }
        else /* no result set or error*/
        {
            /* unsigned int mysql_field_count(MYSQL *mysql) */
            if (mysql_field_count(&mysql) == 0)
            {
                printf("lld rows affected\n");
                break;
            }
        }
        /* more results? -1 = no, >0 = error, 0 = yes (keep looping) */
        if ((status = mysql_next_result(&mysql)) > 0) /* int mysql_next_result(MYSQL *mysql) */
        {
            printf("Counld not execute statement\n");
        }
    } while (status == 0);

    /* step4 void mysql_close(MYSQL *mysql) */
    mysql_close(&mysql);

    /* step5 void mysql_library_end(void) */
    mysql_library_end();

    return EXIT_SUCCESS;
}
  • 接下來切換至代碼路徑下
  • 執(zhí)行編譯指令

gcc -c main.c -I /usr/local/mysql/include

  • 執(zhí)行鏈接指令,得到執(zhí)行文件main

gcc main.o -o main -L /usr/local/mysql/lib -lmysqlclient

  • 此時當前路徑下有這三個文件
main.c main.o main
  • 啟動可執(zhí)行文件main

./main

  • 此時會提示出錯碱屁,解決辦法第一時間應(yīng)該想到的是Mysql官方手冊
  • 根據(jù)官方提供的信息磷脯,可以推斷是系統(tǒng)鏈接的問題。google可得忽媒,由于MacOS系統(tǒng)的保護機制争拐,解決方式如下:

ln -s /usr/local/mysql/lib/libmysqlclient.21.dylib /usr/local/lib/libmysqlclient.21.dylib

  • 最后,啟動可執(zhí)行文件main

./main

  • 前提是你配置好了數(shù)據(jù)庫參數(shù)晦雨,下面是我自己配置的數(shù)據(jù)庫信息
const char host_name[] = "localhost";
const char user_name[] = "root";
const char password[] = "888888";
const char db_name[] = "my_db";

int status = mysql_query(&mysql, "SELECT * FROM Account"); /* int mysql_query(MYSQL *mysql, const char *stmt_str) */
  • SQL語法不懂架曹?SQL手冊了解一下
SELECT * FROM Account
  • 至此,我們使用C語言與MySQL數(shù)據(jù)庫成功實現(xiàn)了數(shù)據(jù)交互闹瞧。

歡迎關(guān)注我的微信公眾號 ArthurSlog

ArthurSlog

如果你喜歡我的文章 歡迎點贊 留言

謝謝

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末绑雄,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子奥邮,更是在濱河造成了極大的恐慌万牺,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件洽腺,死亡現(xiàn)場離奇詭異脚粟,居然都是意外死亡,警方通過查閱死者的電腦和手機蘸朋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進店門核无,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人藕坯,你說我怎么就攤上這事团南。” “怎么了炼彪?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵吐根,是天一觀的道長。 經(jīng)常有香客問我辐马,道長拷橘,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任喜爷,我火速辦了婚禮冗疮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘贞奋。我一直安慰自己赌厅,他們只是感情好,可當我...
    茶點故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布轿塔。 她就那樣靜靜地躺著特愿,像睡著了一般仲墨。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上揍障,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天目养,我揣著相機與錄音,去河邊找鬼毒嫡。 笑死癌蚁,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的兜畸。 我是一名探鬼主播努释,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼咬摇!你這毒婦竟也來了伐蒂?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤肛鹏,失蹤者是張志新(化名)和其女友劉穎逸邦,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體在扰,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡缕减,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了芒珠。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片桥狡。...
    茶點故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖妓局,靈堂內(nèi)的尸體忽然破棺而出总放,到底是詐尸還是另有隱情呈宇,我是刑警寧澤好爬,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站甥啄,受9級特大地震影響存炮,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蜈漓,卻給世界環(huán)境...
    茶點故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一穆桂、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧融虽,春花似錦享完、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽彼绷。三九已至,卻和暖如春茴迁,著一層夾襖步出監(jiān)牢的瞬間寄悯,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工堕义, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留猜旬,地道東北人。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓倦卖,卻偏偏與公主長得像洒擦,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子怕膛,可洞房花燭夜當晚...
    茶點故事閱讀 43,490評論 2 348

推薦閱讀更多精彩內(nèi)容