使用C语言连接MySQL

发布于:2024-12-19 ⋅ 阅读:(8) ⋅ 点赞:(0)

库的准备

要使用C语言连接mysql,需要使用mysql官网提供的connect库,可以去官网下载,由于我们要下载到 Linux 操作系统中,也可以使用如下指令进行安装库

sudo apt-get install libmysqlclient-dev

MySQL连接C/C++的库通常会安装在/usr/include/mysql目录下,您可以通过以下命令检查该目录下是否存在相关的头文件:

ls /usr/include/mysql

库文件通常会安装在/usr/lib/usr/lib64目录下,您可以通过以下命令检查该目录下是否存在相关的库文件:

ls /usr/lib/mysql
ls /usr/lib64/mysql

不过这只是一般的情况,根据版本的不同机器的不同都有差异,其库文件安装的位置也不同,如果安装在非标准路径下,可以使用mysql_config命令来获取正确的编译选项,从而了解到库文件安装的位置:

mysql_config --cflags --libs

我的机器是Ubuntu系统,从显示的结果我们可以看出 -L 后跟着的是 /usr/lib/x86_64-linux-gnu,说明库文件位于/usr/lib/x86_64-linux-gnu下,由于其中文件过多就不展示,实际上我们编译时也可以直接使用 -L /usr/lib

现在我们 尝试链接mysql client,通过 mysql_get_client_info() 函数,来验证我们的引入是否成功。
#include<iostream>
#include <mysql/mysql.h>
using namespace std;
int main()
{
    cout<< "mysql version:" << mysql_get_client_info() <<endl;
}

编译指令如下:

 g++ -o mytest testdb.cc -L /usr/lib -l mysqlclient

其中 -L 后指明了动态库的路径,-l 跟着所要链接的动态库,由于我们在包含头文件时写的是#include <mysql/mysql.h> ,所以不用再指明头文件的具体路径,因为头文件位于 /usr/include/mysql 路径下,而 /usr/include 已经添加到环境变量PATH中,如果包含头文件时写的是#include <mysql.h>,则编译时需要添加 -I /usr/include/mysql ,指明头文件所在路径。

运行结果如下,说明我们已经下载好MySQL连接C/C++的库。

mysql接口介绍

mysql_init

MYSQL *mysql_init(MYSQL *mysql);

该函数用于初始化一个MySQL连接对象。

第一个参数 MYSQL C api中一个非常重要的变量,里面内存非常丰富,有 port,dbname,charset等连接基本参数。
  • 如果mysql是NULL指针,该函数将分配、初始化、并返回新对象。
  • 如果mysql不是NULL指针,该函数将初始化对象,并返回对象的地址。
MYSQL* conn = mysql_create_conn(NULL);

 mysql_real_connect

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

初始化完毕之后,必须先链接数据库,在进行后续操作。(mysql网络部分是基于TCP/IP的)mysql_real_connect用于尝试与运行在主机上的MySQL数据库引擎建立连接。在能够执行需要有效MySQL连接句柄结构的任何其他API函数之前,mysql_real_connect必须成功完成。

  • mysql:这应该是一个已经初始化的MYSQL结构的地址。在调用mysql_real_connect之前,必须调用mysql_init来初始化MYSQL结构。
  • host:主机名或IP地址。如果hostNULL或字符串"localhost",连接将被视为与本地主机的连接。
  • user:用户的MySQL登录ID。如果userNULL或空字符串"",用户将被视为当前用户。
  • passwd:用户的密码。
  • db:数据库名称。如果dbNULL,连接会将默认的数据库设为该值。
  • port:如果不是0,其值将用作TCP/IP连接的端口号。注意,host参数决定了连接的类型。
  • unix_socket:如果不是NULL,该字符串描述了应使用的套接字或命名管道。注意,host参数决定了连接的类型。
  • client_flag:通常为0,但也能设置为特定标志的组合,以允许特定功能,如使用压缩协议、返回发现的行数而非受影响的行数等。

我们可以先使用如下代码来查看是否连接成功,该文件为 testdb.cc

#include<iostream>
#include <mysql/mysql.h>
using namespace std;
int main()
{
    MYSQL* conn=mysql_init(nullptr);   
    if(conn==nullptr)
        cout<<"mysql_init error"<<endl;
    //链接数据库
    mysql_real_connect(conn,"localhost","lbk","2162627569","connect",3306,nullptr,0);
    if(conn==nullptr)
        cout<<"mysql_real_connect error"<<endl;
    else
        cout<<"mysql_real_connect success"<<endl;
    return 0;
}

编译指令

g++ -o mytest testdb.cc -L /usr/lib -l mysqlclient

我们可以看到连接成功。

mysql_query

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

参数:

  • mysql:一个已经初始化的MYSQL对象,表示与MySQL数据库的连接。
  • query:一个以空字符结尾的字符串,包含了要发送的SQL查询语句。

返回值:如果查询成功,函数返回0;如果发生错误,函数返回非零值。

例如我们向connect数据库中的stu表中插入数据

#include <iostream>
#include <mysql/mysql.h>
using namespace std;
int main()
{
    MYSQL *conn = mysql_init(nullptr);
    if (conn == nullptr)
        cout << "mysql_init error" << endl;
    // 链接数据库
    mysql_real_connect(conn, "localhost", "lbk", "2162627569", "connect", 3306, nullptr, 0);
    if (conn == nullptr)
        cout << "mysql_real_connect error" << endl;
    // 执行sql语句
    const char *sql = "insert into stu values(1,'Tom')";
    if (mysql_query(conn, sql) == 0)
        cout << "insert success" << endl;
    return 0;
}

运行程序后,我们可以在MySQL中看到stu表中插入的数据。

mysql_store_result

sql 执行完以后,如果是查询语句,我们当然还要读取数据,如果 update insert等语句,那么就看下操作成功与否即可。我们就需要使用select语句来获取查询结果: 如果mysql_query返回成功,那么我们就通过mysql_store_result这个函数来读取结果。原型如下:
MYSQL_RES *mysql_store_result(MYSQL *mysql);
该函数将查询的全部结果读取到客户端,分配一个MYSQL_RES结构,并将结果置于该结构中,如果读取结果集失败,mysql_store_result也会返回Null指针。以下是 MYSQL_RES结构体的定义:
typedef struct st_mysql_res {
    my_ulonglong row_count;  // 结果集的行数
    unsigned int field_count, current_field;  // 结果集的列数和当前列
    MYSQL_FIELD *fields;  // 结果集的列信息
    MYSQL_DATA *data;  // 结果集的数据
    MYSQL_ROWS *data_cursor;  // 结果集的光标
    MEM_ROOT field_alloc;  // 内存结构
    MYSQL_ROW row;  // 非缓冲的时候用到
    MYSQL_ROW current_row;  // mysql_store_result 时会用到,当前行
    unsigned long *lengths;  // 每列的长度
    MYSQL *handle;  // mysql_use_result 会用
    my_bool eof;  // 是否为行为
} MYSQL_RES;
获得了结果后,我们可以接着调用以下函数来处理结果。
my_ulonglong mysql_num_rows(MYSQL_RES *res);//获取结果行数
unsigned int mysql_num_fields(MYSQL_RES *res);//获取结果列数
mysql_fetch_fields
MYSQL_FIELD *mysql_fetch_fields(MYSQL_RES *res);//获取列的属性

MYSQL_FIELD 结构体是 MySQL C API 中用于表示查询结果集中的字段信息的结构体。它包含了字段的名称、类型、长度等元数据信息。以下是 MYSQL_FIELD 结构体的定义:

typedef struct st_mysql_field {
    char *name; /* 字段名 */
    char *org_name; /* 原始字段名,如果有别名 */
    char *table; /* 字段所属的表名,如果字段是表中的一个字段 */
    char *org_table; /* 原始表名,如果表名有别名 */
    char *db; /* 表所在的数据库名 */
    char *catalog; /* 表的目录名 */
    char *def; /* 字段的默认值 */
    unsigned long length; /* 字段的长度 */
    unsigned long max_length; /* 字段在结果集中的最大长度 */
    unsigned int name_length;
    unsigned int org_name_length;
    unsigned int table_length;
    unsigned int org_table_length;
    unsigned int db_length;
    unsigned int catalog_length;
    unsigned int def_length;
    unsigned int flags; /* 字段的标志 */
    unsigned int decimals; /* 字段的小数位数 */
    unsigned int charsetnr; /* 字段的字符集编号 */
    enum enum_field_types type; /* 字段的类型 */
    void *extension;
} MYSQL_FIELD;

使用案例,列出stu表的列名:

#include <iostream>
#include <mysql/mysql.h>
using namespace std;
int main()
{
    MYSQL *conn = mysql_init(nullptr);
    if (conn == nullptr)
        cout << "mysql_init error" << endl;
    // 链接数据库
    mysql_real_connect(conn, "localhost", "lbk", "2162627569", "connect", 3306, nullptr, 0);
    if (conn == nullptr)
        cout << "mysql_real_connect error" << endl;
    // 执行sql语句
    // const char *sql = "insert into stu values(1,'Tom')";
    const char *sql1 = "insert into stu values(2,'Jane')";
    mysql_query(conn, sql1);
    const char *sql2 = "insert into stu values(3,'Jake')";
    mysql_query(conn, sql2);
    const char *sql3 = "select * from stu";
    mysql_query(conn, sql3);
    MYSQL_RES *res = mysql_store_result(conn);
    int fnum = mysql_num_fields(res);
    MYSQL_FIELD *field = mysql_fetch_fields(res);
    for (int i = 0; i < fnum; i++)
    {
        cout << field[i].name << " ";
    }
    cout << endl;
    return 0;
}

结果如下:

如果我们需要列的更多属性,可以按照结构体中的内容找出。
mysql_fetch_row
MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);
MYSQL_ROW结构体在 MySQL C API 中用于表示查询结果集中的一行数据。它实际上是一个指向字符串数组的指针,其中每个字符串对应结果集中的一个字段值。以下是 MYSQL_ROW 结构体的定义:
typedef char **MYSQL_ROW;

MYSQL_ROW 结构体没有显式定义的成员变量,因为它本质上是一个二级指针,指向一个字符串数组。数组中的每个元素都是一个以 null 结尾的字符串,代表结果集中的一个字段值。

mysql_close

void mysql_close(MYSQL *mysql);

mysql_close函数用于关闭与MySQL数据库的连接。这个函数是MySQL C API的一部分,通常在完成数据库操作后调用,以释放与数据库连接相关的资源。