MySQL 使用 C 语言连接

一、mysql connect

我们之前已经学习过 mysql 的基础,后面我们只关心如何使用 C 语言连接 mysql。

要使用 C 语言连接 mysql,需要使用 mysql 官网提供的库,大家可以去官网下载。

我们使用 C 接口库来进行连接。

二、准备工作

要正确使用 C 语言连接 mysql,我们需要做一些准备工作:

  • 保证 mysql 服务有效。
  • 在官网上下载合适自己平台的 mysql connect 库,以备后用。

三、Connector/C 使用

我们下载下来的库格式如下:

.
├── include
│   ├── big_endian.h
│   ├── byte_order_generic.h
│   ├── byte_order_generic_x86.h
│   ├── decimal.h
│   ├── errmsg.h
│   ├── keycache.h
│   ├── little_endian.h
│   ├── m_ctype.h
│   ├── m_string.h
│   ├── my_alloc.h
│   ├── my_byteorder.h
│   ├── my_compiler.h
│   ├── my_config.h
│   ├── my_dbug.h
│   ├── my_dir.h
│   ├── my_getopt.h
│   ├── my_global.h
│   ├── my_list.h
│   ├── my_pthread.h
│   ├── mysql
│   │   ├── client_authentication.h
│   │   ├── client_plugin.h
│   │   ├── client_plugin.h.pp
│   │   ├── get_password.h
│   │   ├── plugin_auth_common.h
│   │   ├── plugin_trace.h
│   │   ├── psi
│   │   │   ├── mysql_file.h
│   │   │   ├── mysql_idle.h
│   │   │   ├── mysql_mdl.h
│   │   │   ├── mysql_memory.h
│   │   │   ├── mysql_ps.h
│   │   │   ├── mysql_socket.h
│   │   │   ├── mysql_sp.h
│   │   │   ├── mysql_stage.h
│   │   │   ├── mysql_statement.h
│   │   │   ├── mysql_table.h
│   │   │   ├── mysql_thread.h
│   │   │   ├── mysql_transaction.h
│   │   │   ├── psi_base.h
│   │   │   ├── psi.h
│   │   │   └── psi_memory.h
│   │   ├── service_my_snprintf.h
│   │   └── service_mysql_alloc.h
│   ├── mysql_com.h
│   ├── mysql_com_server.h
│   ├── mysqld_ername.h
│   ├── mysqld_error.h
│   ├── mysql_embed.h
│   ├── mysql.h
│   ├── mysql_time.h
│   ├── mysql_version.h
│   ├── my_sys.h
│   ├── my_xml.h
│   ├── sql_common.h
│   ├── sql_state.h
│   ├── sslopt-case.h
│   ├── sslopt-longopts.h
│   ├── sslopt-vars.h
│   └── typelib.h
└── lib
    ├── libmysqlclient.a
    ├── libmysqlclient_r.a -> libmysqlclient.a
    ├── libmysqlclient_r.so -> libmysqlclient.so
    ├── libmysqlclient_r.so.18 -> libmysqlclient.so.18
    ├── libmysqlclient_r.so.18.3.0 -> libmysqlclient.so.18.3.0
    ├── libmysqlclient.so -> libmysqlclient.so.18
    ├── libmysqlclient.so.18 -> libmysqlclient.so.18.3.0
    └── libmysqlclient.so.18.3.0

其中 include 包含所有的方法声明,lib 包含所有的方法实现(打包成库)。

四、尝试链接 mysql client

通过 mysql_get_client_info() 函数,来验证我们的引入是否成功。

#include<iostream>
#include<mysql/mysql.h>

using namespace std;

int main()
{
    cout<<"mysql client version: "<<mysql_get_client_info()<<endl;
    return 0;
}
[root@localhost testdb]# ll
total 4
-rw-rw-r--. 1 lll lll 512 Aug  6 15:30 test.cc
[root@localhost testdb]# g++ -o mytest test.cc -L/lib64/mysql -lmysqlclient
[root@localhost testdb]# ll
total 24
-rwxr-xr-x. 1 root root 17160 Aug  6 15:32 mytest
-rw-rw-r--. 1 lll  lll    512 Aug  6 15:30 test.cc
[root@localhost testdb]# ./mytest 
mysql client version: 5.7.44

五、mysql 接口介绍

makefile

mytest:test.cc
	g++ -o mytest test.cc -std=c++11 -L/lib64/mysql -lmysqlclient
.PHONY:
clean:
	rm -rf mytest

(一)初始化 mysql_init()

要使用库,必须先进行初始化!

MYSQL *mysql_init(MYSQL *mysql);

例如:MYSQL *mfp = mysql_init(NULL)

(二)链接数据库 mysql_real_connect

初始化完毕之后,必须先链接数据库,在进行后续操作。(mysql 网络部分是基于 TCP/IP 的)

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 clientflag);

第一个参数 MYSQL 是 Capi 中一个非常重要的变量(mysql_init 的返回值),里面内存非常丰富,有 port、dbname、charset 等连接基本参数。

它也包含了一个叫 st_mysql_methods 的结构体变量,该变量里面保存着很多函数指针,这些函数指针将会在数据库连接成功以后的各种数据操作中被调用。

mysql_real_connect 函数中各参数基本都是顾名思义。

(三)下发 mysql 命令 mysql_query

第一个参数上面已经介绍过,第二个参数为要执行的 sql 语句,如 “select * from table”。

int mysql_query(MYSQL *mysql, const char *q);

(四)获取执行结果mysql_store_result

sql 执行完以后,如果是查询语句,我们当然还要读取数据,如果 update、insert 等语句,那么就看下操作成功与否即可。

我们来看看如何获取查询结果:如果 mysql_query 返回成功,那么我们就通过 mysql_store_result 这个函数来读取结果。

原型如下:

MYSQL_RES *mysql_store_result(MYSQL *mysql);

该函数会调用 MYSQL 变量中的 st_mysql_methods 中的 read_rows 函数指针来获取查询的结果。

同时该函数会返回 MYSQL_RES 这样一个变量,该变量主要用于保存查询的结果。

同时该函数 malloc 了一片内存空间来存储查询过来的数据,所以我们一定要记得 free(result),不然是肯定会造成内存泄漏的。

执行完 mysql_store_result 以后,其实数据都已经在 MYSQL_RES 变量中了,下面的 api 基本就是读取 MYSQL_RES 中的数据。

img

(五)获取结果行数 mysql_num_rows

my_ulonglong mysql_num_rows(MYSQL_RES *res);

(六)获取结果列数 mysql_num_fields

unsigned int mysql_num_fields(MYSQL_RES *res);

(七)获取列名 mysql_fetch_fields

MYSQL_FIELD *mysql_fetch_fields(MYSQL_RES *res);

(八)获取结果内容 mysql_fetch_row

MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);

它会返回一个 MYSQL_ROW 变量,MYSQL_ROW 其实就是 char **. 就当成一个二维数组来用吧。

(九)关闭 mysql 链接 mysql_close

void mysql_close(MYSQL *sock);

另外,mysql C api 还支持事务等常用操作,大家下来自行了解:

my_bool STDCALL mysql_autocommit(MYSQL * mysql, my_bool auto_mode);
my_bool STDCALL mysql_commit(MYSQL * mysql);
my_bool STDCALL mysql_rollback(MYSQL * mysql);

test.cc

#include<iostream>
#include<string>
#include<unistd.h>
#include<mysql/mysql.h>

using namespace std;

// const string host="127.0.0.1";
const string host="localhost";
const string user="connector";
const string passwd="123456";
const string db="conn";
const unsigned int port=3306;

int main()
{
    // cout<<"mysql client version: "<<mysql_get_client_info()<<endl;
    MYSQL*my=mysql_init(nullptr);
    if(my==nullptr)
    {
        cerr<<"Mysql init error"<<endl;
        return 1;
    }
    cout<<"Mysql init success"<<endl;
    
    if(mysql_real_connect(my,host.c_str(),user.c_str(),passwd.c_str(),db.c_str(),port,nullptr,0)==nullptr)
    {
        cerr<<"Mysql connect error"<<endl;
        return 2;
    }
    cout<<"Mysql connect success"<<endl;
    mysql_set_character_set(my,"utf8");

    // string sql="update user set name='Tom' where id=3";
    // string sql="insert into user (name,age,telphone) values ('王五',18,'66666666') ";
    // string sql="delete from user where id=2";
    string sql="select* from user";

    int n=mysql_query(my,sql.c_str());
    if(n==0)
    {
        cout<<sql<<" succuss: "<<n<<endl;
    }
    else
    {
        cerr<<sql<<" fail: "<<n<<endl;
        return 3;
    }

    MYSQL_RES*res=mysql_store_result(my);
    if(res==nullptr)
    {
        cerr<<"mysql_store_result error"<<endl;
        return 4;
    }

    int rows=mysql_num_rows(res);
    int fields=mysql_num_fields(res);

    cout<<"行: "<<rows<<endl;
    cout<<"列: "<<fields<<endl;

    //表的属性
    MYSQL_FIELD*field_array=mysql_fetch_fields(res);
    for(int i=0;i<fields;i++)
    {
        cout<<field_array[i].name<<"\t";
    }
    cout<<endl;

    //表的内容
    for(int i=0;i<rows;i++)
    {
        MYSQL_ROW row=mysql_fetch_row(res);
        for(int j=0;j<fields;j++)
        {
            cout<<row[j]<<"\t";
        }
        cout<<endl;
    }

    // string sql;
    // while(1)
    // {
    //     cout<<"mysql >>> ";
    //     if(!getline(cin,sql)||sql=="quit")
    //     {
    //         cout<<"bye bye"<<endl;
    //         break;
    //     }
    //     int n=mysql_query(my,sql.c_str());
    //     if(n==0)
    //     {
    //         cout<<sql<<" succuss: "<<n<<endl;
    //     }
    //     else
    //     {
    //         cerr<<sql<<" fail: "<<n<<endl;
    //     }
    // }

    mysql_free_result(res);
    mysql_close(my);
    return 0;
 }

img

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐