当我们在项目中需要用C语言和MySQL数据库进行交互时,可以使用基于C语言的MySQL接口来进行对数据的增、删、改、查等操作。这篇文章将从基于C的MySQL接口及示例做相关学习和总结。
1.MySQL C语言API相关数据类型
(1)MYSQL结构体
对一个数据库进行操作之前,必须进行连接,该数据结构是创建连接所必要的句柄,其实质是一个结构体,包含的内容较多,了解一下即可:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
typedef struct st_mysql { NET net; unsigned char *connector_fd; char *host,*user,*passwd,*unix_socket,*server_version,*host_info; char *info, *db; struct charset_info_st *charset; MYSQL_FIELD *fields; MEM_ROOT field_alloc; my_ulonglong affected_rows; my_ulonglong insert_id; my_ulonglong extra_info; unsigned long thread_id; unsigned long packet_length; unsigned int port; unsigned long client_flag,server_capabilities; unsigned int protocol_version; unsigned int field_count; unsigned int server_status; unsigned int server_language; unsigned int warning_count; struct st_mysql_options options; enum mysql_status status; my_bool free_me; my_bool reconnect; char scramble[SCRAMBLE_LENGTH+1]; my_bool unused1; void *unused2, *unused3, *unused4, *unused5; LIST *stmts; const struct st_mysql_methods *methods; void *thd; my_bool *unbuffered_fetch_owner; char *info_buffer; void *extension; } MYSQL; |
(2)MYSQL_RES结构体
函数mysql_store_result和mysql_use_result的返回类型就是MYSQL_RES,该结构体中包含了查询的结果集:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
typedef struct st_mysql_res { my_ulonglong row_count; MYSQL_FIELD *fields; MYSQL_DATA *data; MYSQL_ROWS *data_cursor; unsigned long *lengths; /* column lengths of current row */ MYSQL *handle; /* for unbuffered reads */ const struct st_mysql_methods *methods; MYSQL_ROW row; /* If unbuffered read */ MYSQL_ROW current_row; /* buffer to current row */ MEM_ROOT field_alloc; unsigned int field_count, current_field; my_bool eof; /* Used by mysql_fetch_row */ my_bool unbuffered_fetch_cancelled; void *extension; } MYSQL_RES; |
(3)MYSQL_ROW
该变量是对结果集中的一行数据的类型安全的表示,其实质就是一个指向char类型的二级指针:
1 |
typedef char **MYSQL_ROW; /* return data as array of strings */ |
并且,函数mysql_fetch_row的返回类型就是MYSQL_ROW。(其形参类型是MYSQL_RES *)
(4)MYSQL_FIELD结构体
该结构体描述了数据库中表字段的各种信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
typedef struct st_mysql_field { char *name; /* Name of column */ char *org_name; /* Original column name, if an alias */ char *table; /* Table of column if column was a field */ char *org_table; /* Org table name, if table was an alias */ char *db; /* Database for table */ char *catalog; /* Catalog for table */ char *def; /* Default value (set by mysql_list_fields) */ unsigned long length; /* Width of column (create length) */ unsigned long max_length; /* Max width for selected set */ 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; /* Div flags */ unsigned int decimals; /* Number of decimals in field */ unsigned int charsetnr; /* Character set */ enum enum_field_types type; /* Type of field. See mysql_com.h for types */ void *extension; } MYSQL_FIELD; |
并且,函数mysql_fetch_field和mysql_fetch_fields返回类型就是MYQL_FIELD *。前者返回表的下一个字段,后者返回表的所有字段的数组。
2.MySQL C语言API
(1)mysql_init
原型:MYSQL * STDCALL mysql_init(MYSQL *mysql);
功能:初始化MYSQL结构
返回值:成功返回MYSQL句柄;失败返回NULL。
其中关键字STDCALL是一个宏定义:#define STDCALL __stdcall,而__stdcall是函数调用约定的一种,被这个关键字修饰的函数,其参数都是从右向左通过堆栈传递的, 函数调用在返回前要由被调用者清理堆栈。
(2)mysql_options
原型:int STDCALL mysql_options(MYSQL *mysql, enum mysql_option option, const char *arg);
功能:为mysql_real_connect设置连接选项
返回值:成功返回0;如果指定了一个位置选项,返回非0
其中,第二个参数是一个枚举型,里面包含了众多选项,可参考mysql.h头文件。
(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服务器。
返回值:成功返回一个连接的MYSQL句柄;失败返回NULL。
注:原mysql_connect函数已经被mysql_real_connect函数取代了。
(4)mysql_query
原型:int STDCALL mysql_query(MYSQL *mysql, const char *q);
功能:执行以“NULL结束”的字符串SQL查询
返回值:成功返回0;失败返回非零
(5)mysql_real_query
原型:int STDCALL mysql_real_query(MYSQL *mysql, const char *q, unsigned long length);
功能:执行以“指定长度”的字符串SQL查询
返回值:成功返回0;失败返回非0
(6)mysql_errno
原型:unsigned int STDCALL mysql_errno(MYSQL *mysql);
功能:返回上一次调用MySQL函数的错误编号
返回值:返回上次调用接口出错的错误编号;返回0表示上次调用正常
(7)mysql_ping
原型:int STDCALL mysql_ping(MYSQL *mysql);
功能:检查与服务器的连接是否正常,如有必要重新连接
返回值:连接正常返回0;连接异常返回非零
(8)mysql_store_result
原型:MYSQL_RES * STDCALL mysql_store_result(MYSQL *mysql);
功能:将检索完整的结果集返给客户端(Retrieves a complete result set to the client)
返回值:成功返回类型为MYSQL_RES*的结果集;失败返回NULL
(9)mysql_num_rows
原型:my_ulonglong STDCALL mysql_num_rows(MYSQL_RES *result);
功能:返回结果集中的行数
返回值:返回结果集中的行数
其中返回类型有:typedef unsigned long my_ulonglong;
(10)mysql_free_result
原型:void STDCALL mysql_free_result(MYSQL_RES *result);
功能:释放结果集使用的内存
返回值:无返回值
(11)mysql_fetch_row
原型:MYSQL_ROW STDCALL mysql_fetch_row(MYSQL _RES *result);
功能:从结果集中获取下一行
返回值:返回下一行MYSQL_ROW结构;出错或者结果集中没有更多的内容时返回NULL
(12)mysql_num_fields
原型:unsigned int STDCALL mysql_num_fields(MYSQL_RES *result);
功能:返回结果集中的列数
返回值:返回结果集中的列数
(13)mysql_fetch_field
原型:MYSQL_FIELD * STDCALL mysql_fetch_field(MYSQL_RES *result);
功能:返回下一表字段类型
返回值:返回当前字段的MYSQL_FIELD结构体;没有更多的字段返回NULL
(14)mysql_fetch_fields
原型:MYSQL_FIELD *STDCALL mysql_fetch_fields(MYSQL_RES *result);
功能:返回所有字段结构的数组
返回值:返回结果集中所有字段的MYSQL_FIELD结构体数组
(15)mysql_close
原型:void STDCALL mysql_close(MYSQL *mysql);
功能:关闭连接
返回值:无返回值
3.示例
首先,在数据库“dulishu”中创建一个“student”表,并插入两条内容,如下所示:
1 2 3 4 5 6 7 8 |
mysql> select * from student; +----+------+ | id | name | +----+------+ | 1 | leo | | 2 | lee | +----+------+ 2 rows in set (0.00 sec) |
编写如下示例程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "mysql.h" int main(void) { MYSQL mysql; MYSQL_RES *result; MYSQL_ROW row; MYSQL_FIELD *field; char szSql[1024]; //存储SQL语句 int nColumn, nRow; //查询的表字段数、行数 char szColumn[1024][1024]; //存储字段 char szRow[1024][1024]; //存储行数据 mysql_init(&mysql); //初始化mysql句柄 mysql_real_connect(&mysql, "localhost", "root", "666666", "dulishu", 3306, NULL, 0); //连接 memset(szSql, 0, sizeof(szSql)); sprintf(szSql, "select * from student"); mysql_query(&mysql, szSql); //执行SQL语句进行查询 /*将查询结果存储在result指向的结构体中*/ result = mysql_store_result(&mysql); if(result){ int i,j; nColumn = mysql_num_fields(result); //获得查询表的字段数 /*逐个获取字段,并存储*/ for(i = 0; i < nColumn; i++){ field = mysql_fetch_field(result); memset(szColumn[i], 0, sizeof(szColumn[i])); strcpy(szColumn[i], field->name); } nRow = mysql_num_rows(result); //获得查询表的行数 printf("Found %d rows of the result.\n", nRow); printf("Print the result:\n"); /*打印输出表字段*/ for(i = 0; i < nColumn; i++){ printf("%s\t", szColumn[i]); } printf("\n"); /*逐个获取查询到的每行数据,并将每行数据存储下来,然后打印输出*/ i = 0; while(i < nRow){ row = mysql_fetch_row(result); for(j = 0; j < nColumn; j++){ memset(szRow[j], 0, sizeof(szRow[j])); strcpy(szRow[j], row[j]); printf("%s\t", szRow[j]); } printf("\n"); i++; } } mysql_free_result(result); mysql_close(&mysql); return 0; } |
编译运行:
1 2 3 4 5 6 7 8 |
# gcc -Wall -g mysqlDemo1.c -o mysqlDemo1 -I /usr/local/mysql/include/ -L /usr/local/mysql/lib/ -lmysqlclient # ./mysqlDemo1 Found 2 rows of the result. Print the result: id name 1 leo 2 lee # |
示例中展示了C语言调用MySQL接口的一个简单的示例,并没有对函数调用进行错误判断等操作。实际项目中可能要更为复杂,比如使用mysql_errno函数对调用结果进行错误判断,设计数据库结构体将查询结果存入,或从数据库结构体中读入数据去更新表的内容等等。
并且,文中只列举了几个基础的接口函数,其他函数可以参考MySQL官方文档,地址如下:
https://dev.mysql.com/doc/refman/5.7/en/c-api-function-overview.html