通过C语言的API连接MySQL数据库

一、如何连接MySQL

C的API文档地址:https://www.mysqlzh.com/doc/194.html

首先需要安装MySQL

sudo apt-get update
sudo apt-get install mysql-server

C语言的API代码是与MySQL一起提供的,它包含在mysqlclient库中,并允许C程序访问数据库,如果安装MySQL后仍提示缺少库,则需要安装如下:

sudo apt-get install libmysqlclient-dev
sudo apt-get install libmysql++-dev

与MySQL交互时,应用程序应使用以下步骤:

  • 通过调用mysql_library_init(),初始化MySQL库。库可以是mysqlclient C客户端,或mysqld嵌入式服务器库,具体情况取决于应用程序是否与"-libmysqlclient"或"-libmysqld"标志连接。
  • 通过调用mysql_init()初始化连接处理程序,并通过调用mysql_connect()连接到服务器。
  • 发出SQL语句并处理其结果。
  • 通过调用mysql_close(),关闭于MySQL服务器的连接。
  • 通过调用mysql_library_end(),结束MySQL库的使用。

调用mysql_library_init()和mysql_library_end()的目的在于为MySQL库提供恰当的初始化和结束处理。对于与客户端库链接的应用程序,它们提供了改进的内存管理功能,如果不调用mysql_library_end(),内存块仍将保持分配状态(这不会增加应用程序的内存量,但某些内存泄漏器将会抗议它)。对于与嵌入式服务器链接的应用程序,这些调用会启动并停止服务器。mysql_library_init()和mysql_library_end()实际上是#define符号,这类符号使得它们等效于mysql_server_init()和mysql_server_end(),但其名称更清楚地指明,无论应用程序使用的mysqkclient或mysqld库,启动或结束MySQ库时,应用调用它们。对于早期的MySQL版本,可调用mysql_server_init()和mysql_server_end()取而代之。如果愿意,可省略对mysql_library_init()的调用,这是因为,必要时,mysql_init()会自动调用它。

二、相关函数介绍

1.mysql_init()

MYSQL *STDCALL mysql_init(MYSQL *mysql);

描述:分配或初始化与mysql_real_connect()相适应的MYSQL对象,如果mysql是NULL指针,该函数将分配、初始化、并返回新对象。否则,将初始化对象,并返回对象的地址,如果mysql_init()分配了新的对象,当调用mysql_close()来关闭连接时,将释放该对象。

返回值:初始化的MYSQL*句柄,如果无足够的内存以分配新的对象,返回NULL。

错误:在内存不足的情况下,返回NULL。

2.mysql_close()

void STDCALL mysql_close(MYSQL *sock);

描述:关闭前面打开的连接,如果句柄是由mysql_init()或mysql_connect()自动分配的,mysql_close()还将解除分配由mysql指向的连接句柄。

3.mysql_real_connect()

MYSQL *STDCALL 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_real_connect()尝试与运行在主机上的MySQL数据库引擎建立连接,在能够执行需要有效MySQL连接句柄结构的任何其他API函数之前,所有mysql_real_connect()必须成功完成。

参数的指定方式如下:

  • mysql:已有的MYSQL结构的地址,调用mysql_real_connect()之前,必须调用mysql_init()来初始化MYSQL结构。通过mysql_option()调用,可更改连接选项。
  • host:必须是主机名或IP地址,如果host是NULL或字符串"localhost",连接将被视为与本地主机的连接。
  • user:包含用户的MySQL登录ID,如果user是NULL或空字符串"",用户将被视为当前用户。在UNIX环境下,它是当前的登陆名。
  • passwd:包含用户的密码,如果passwd是NULL,仅会对该用户的(拥有1个空密码字段的)用户表中的条目进行匹配检查。这样,数据库管理员就能按特定的方式设置MySQL权限系统,根据用户是否拥有指定的密码,用户将获得不同的权限。
  • db:是数据库名称,如果db为NULL,连接会将默认的数据库设为该值。
  • port:如果port不是0,其值将用于TCP/IP连接的端口号,注意,"host"参数决定了连接的类型。
  • unix_socket:如果值不是NULL,该字符串描述了应使用的套接字或命名管道,注意,"host"参数决定了连接的类型。
  • clientflag:值通常为0。

对于某些参数,能够从选项文件获得取值,而不是取得mysql_real_connect()调用中的确切值,为此,在调用mysql_real_connect()之前,应与MYSQL_READ_DEFAULT_FILE或MYSQL_READ_DEFAULT_GROUP选项一起调用mysql_option()。随后,在mysql_real_connect()调用中,为准备选项文件读取值的每个参数指定"无值"值。

  • 对于host,指定NULL值或空字符串("")。
  • 对于user,指定NULL值或空字符串。
  • 对于passwd,指定NULL值。(对于密码,调用中的空字符串的值不能被选项文件中的字符串覆盖,这是因为空字符串明确指明MySQL账户必须由空密码)。
  • 对于db,指定NULL值或空字符串。
  • 对于port,指定"0"值。
  • 对于unix_socket,指定NULL值

对于某一参数,如果在选项文件中未发现值,将使用它的默认值。

返回值:如果连接成功,返回MYSQL*连接句柄,如果连接失败,返回NULL,对于成功的连接,返回值与第一个参数的值相同。  

错误:

  • CR_CONN_HOST_ERROR:无法连接到MySQL服务器。
  • CR_CONNECTION_ERROR:无法连接到本地MySQL服务器。 

4.mysql_query()

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

描述:

执行由“Null终结的字符串”查询指向的SQL查询。正常情况下,字符串必须包含1条SQL语句,而且不应为语句添加终结分号(‘;’)或“\g”。如果允许多语句执行,字符串可包含多条由分号隔开的语句。mysql_query()不能用于包含二进制数据的查询,应使用mysql_real_query()取而代之(二进制数据可能包含字符‘\0’,mysql_query()会将该字符解释为查询字符串结束)。如果希望了解查询是否应返回结果集,可使用mysql_field_count()进行检查。

返回值:

如果查询成功,返回0。如果出现错误,返回非0值。 

5.mysql_real_query()

int mysql_real_query(MYSQL *mysql, const char *query, unsigned long length); 

描述: 

执行由“query”指向的SQL查询,它应是字符串长度字节“long”。正常情况下,字符串必须包含1条SQL语句,而且不应为语句添加终结分号(‘;’)或“\g”。如果允许多语句执行,字符串可包含由分号隔开的多条语句。“多查询执行的C API处理”。对于包含二进制数据的查询,必须使用mysql_real_query()而不是mysql_query(),这是因为,二进制数据可能会包含‘\0’字符。此外,mysql_real_query()比mysql_query()快,这是因为它不会在查询字符串上调用strlen()。

返回值:如果查询成功,返回0,如果出现错误,返回非0值。

6.mysql_error()

const char *mysql_error(MYSQL *mysql);

描述:对于由mysql指定的连接,对于失败的最近调用的API函数,mysql_error()返回包含错误消息的、由Null终结的字符串。如果该函数未失败,mysql_error()的返回值可能是以前的错误,或指明无错误的空字符串。

返回值:返回描述错误的、由Null终结的字符串。如果未出现错误,返回空字符串。

7.mysql_store_result()

MYSQL_RES *mysql_store_result(MYSQL *mysql);

描述:

对于成功检索了数据的每个查询(SELECT、SHOW、DESCRIBE、EXPLAIN、CHECK TABLE等),必须调用mysql_store_result()或mysql_use_result() 。mysql_store_result()将查询的全部结果读取到客户端,分配1个MYSQL_RES结构,并将结果置于该结构中。如果查询未返回结果集,mysql_store_result()将返回Null指针(例如,如果查询是INSERT语句)。如果读取结果集失败,mysql_store_result()还会返回Null指针。通过检查mysql_error()是否返回非空字符串。一旦调用了mysql_store_result()并获得了不是Null指针的结果,可调用mysql_num_rows()来找出结果集中的行数。一旦完成了对结果集的操作,必须调用mysql_free_result()。

返回值:具有多个结果的MYSQL_RES结果集合。如果出现错误,返回NULL。

8.mysql_num_rows()

my_ulonglong mysql_num_rows(MYSQL_RES *result);

描述:返回结果集中的行数。mysql_num_rows()的使用取决于是否采用了mysql_store_result()或mysql_use_result()来返回结果集。如果使用了mysql_store_result(),可以立刻调用mysql_num_rows()。如果使用了mysql_use_result(),mysql_num_rows()不返回正确的值,直至检索了结果集中的所有行为止。

返回值:结果集中的行数。

9.mysql_num_fields()

unsigned int mysql_num_fields(MYSQL_RES *result); 

返回值:结果集的列数。

10.mysql_fetch_row()

MYSQL_ROW mysql_fetch_row(MYSQL_RES *result) ;

描述:

检索结果集的下一行。在mysql_store_result()之后使用时,如果没有要检索的行,mysql_fetch_row()返回NULL。在mysql_use_result()之后使用时,如果没有要检索的行或出现了错误,mysql_fetch_row()返回NULL。行内值的数目由mysql_num_fields(result)给出。如果行中保存了调用mysql_fetch_row()返回的值,将按照row[0]到row[mysql_num_fields(result)-1],访问这些值的指针。行中的NULL值由NULL指针指明。可以通过调用mysql_fetch_lengths()来获得行中字段值的长度。对于空字段以及包含NULL的字段,长度为0。通过检查字段值的指针,能够区分它们。如果指针为NULL,字段为NULL,否则字段为空。

返回值:下一行的MYSQL_ROW结构。如果没有更多要检索的行或出现了错误,返回NULL。

11.mysql_fetch_lengths()

unsigned long *mysql_fetch_lengths(MYSQL_RES *result) 

描述:返回结果集内当前行的列的长度。如果打算复制字段值,该长度信息有助于优化,这是因为,你能避免调用strlen()。此外,如果结果集包含二进制数据,必须使用该函数来确定数据的大小,原因在于,对于包含Null字符的任何字段,strlen()将返回错误的结果。对于空列以及包含NULL值的列,其长度为0。

返回值:无符号长整数的数组表示各列的大小(不包括任何终结NULL字符)。如果出现错误,返回NULL。

12.mysql_fetch_fields()

MYSQL_FIELD *mysql_fetch_fields(MYSQL_RES *result);

描述:对于结果集,返回所有MYSQL_FIELD结构的数组。每个结构提供了结果集中1列的字段定义。

返回值:关于结果集所有列的MYSQL_FIELD结构的数组。  

三、执行插入、删除、修改等SQL语句

示例如下:

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

#define HOST_IP     "localhost"
#define USER_NAME   "root"
#define USER_PWD    "root"
#define DB_NAME     "mydb"

int main() {
    MYSQL *mysql = NULL;

    //初始化
    mysql = mysql_init(NULL);
    if (mysql == NULL) {
        printf("mysql_init failde...\n");

        return  -1;
    }
    printf("mysql_init successfully...\n");

    //连接数据库
    mysql = mysql_real_connect(mysql, HOST_IP, USER_NAME, USER_PWD, DB_NAME, 0, NULL, 0);
    if (mysql == NULL) {
        printf("mysql_real_connect failed:%s\n", mysql_error(mysql));

        return -1;
    }
    printf("mysql_real_connect successfully...\n");

    char buffer[128] = {0};

    //插入数据
    strncpy(buffer, "insert into student(id,name,chinese,english,math) values(11,'张三',93,95,91)", sizeof (buffer));
    int ret = mysql_query(mysql, buffer);
    if (ret != 0) {
        printf("mysql_query insert failed:%s\n", mysql_error(mysql));
        mysql_close(mysql);

        return -1;
    }
    printf("insert data successfully...\n");

    memset(buffer, 0, sizeof(buffer));

    //删除数据
    strncpy(buffer, "delete from student where id=1", sizeof (buffer));
    ret = mysql_query(mysql, buffer);
    if (ret != 0) {
        printf("mysql_query delete failed:%s\n", mysql_error(mysql));
        mysql_close(mysql);

        return -1;
    }
    printf("delete data successfully...\n");

    memset(buffer, 0, sizeof(buffer));

    //修改数据
    strncpy(buffer, "update student set name='范冰冰' where id=4", sizeof (buffer));
    ret = mysql_query(mysql, buffer);
    if (ret != 0) {
        printf("mysql_query update failed:%s\n", mysql_error(mysql));
        mysql_close(mysql);

        return -1;
    }
    printf("update data successfully...\n");

    //关闭连接
    mysql_close(mysql);

    return 0;
}

四、执行select语句并输出结果

示例如下所示:

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

#define HOST_IP     "localhost"
#define USER_NAME   "root"
#define USER_PWD    "root"
#define DB_NAME     "mydb"

int main() {
    MYSQL *mysql = NULL;
    MYSQL_RES *res = NULL;
    MYSQL_ROW row = NULL;
    unsigned int i;

    //初始化
    mysql = mysql_init(NULL);
    if (mysql == NULL) {
        printf("mysql_init failde...\n");

        return  -1;
    }
    printf("mysql_init successfully...\n");

    //连接数据库
    mysql = mysql_real_connect(mysql, HOST_IP, USER_NAME, USER_PWD, DB_NAME, 0, NULL, 0);
    if (mysql == NULL) {
        printf("mysql_real_connect failed:%s\n", mysql_error(mysql));

        return -1;
    }
    printf("mysql_real_connect successfully...\n");

    char buffer[128] = {0};

    //执行select语句
    strncpy(buffer, "select * from student", sizeof (buffer));
    int ret = mysql_query(mysql, buffer);
    if (ret != 0) {
        printf("mysql_query failed:%s\n", mysql_error(mysql));
        mysql_close(mysql);

        return -1;
    }

    //获取结果集
    res = mysql_store_result(mysql);
    if (res == NULL) {
        printf("mysql_store_result failed:%s\n", mysql_error(mysql));
        mysql_close(mysql);

        return  -1;
    }
    printf("mysql_store_result successfully...\n");

    //获取结果集中的行数
    printf("row:%lu\n", mysql_num_rows(res));

    //获取结果集中的列数
    printf("column:%u\n", mysql_num_fields(res));

    //获取字段数量
    unsigned int num_fields = mysql_num_fields(res);
    //获取字段信息
    MYSQL_FIELD *fields = mysql_fetch_fields(res);

    while (1) {
        unsigned int flag = 0;
        row = mysql_fetch_row(res);
        if (row == NULL) {
            break;
        }

        for (i = 0; i < num_fields; i++) {
            flag++;
            printf("%s:%s ", fields[i].name, row[i] ? row[i] : "NULL");
            if (flag == num_fields) {
                printf("\n");
            }
        }
    }
    printf("\n");

    //释放结果集
    mysql_free_result(res);

    //关闭连接
    mysql_close(mysql);

    return 0;
}

数据表数据显示:  

查询结果显示:

  

 
posted @ 2023-12-08 18:00  TechNomad  阅读(118)  评论(0编辑  收藏  举报