分享

Mysql C API

 wellbeing_wang 2011-08-23

1. 简介

除了通过DBD::mysql来访问MySQL服务器之外,我们还可以通过MySQL C API来直接访问MySQL服务器,这需要使用mysqlclient库,MySQL的大多数客户端API(除了Java和.NET)都是通过这个库来和MySQL服务器通讯的,而这个库正是用C编写的。

下面简单介绍如何通过MySQL C API来访问MySQL服务器,函数的详细说明请参考《MySQL参考手册》。

2. 代码编写和编译

在源代码中需要加入

#include <mysql.h>

在编译时需要加入以下参数(假设MySQL安装位置为/usr/local/mysql, 非RPM方式安装)

-I/usr/local/mysql/include -L/usr/local/mysql/lib -lmysqlclient

3. 连接MySQL服务器

在连接MySQL服务器之前,需要初始化一个MYSQL结构,该结构在几乎所有的MySQL C API函数(除了预处理语句相关的函数)中都会用到。

MYSQL *mysql_init(MYSQL *mysql)

然后就可以连接MySQL服务器了。

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_READ_DEFAULT_FILE作为选项名来调用mysql_options(), 再调用mysql_real_connect()来连接服务器

mysql_options(*mysql, MYSQL_READ_DEFAULT_FILE, "my.cnf")
mysql_real_connect(*mysql, NULL, NULL, NULL, NULL, 0, NULL, 0)

my.cnf文件中记录了连接MySQL服务器所需的各项参数(地址,端口,用户名,密码,数据库,字符集,Unix Socket等)。这样可以灵活的修改连接参数而不必重新编译程序。

如果要关闭连接,则调用mysql_close()

void mysql_close(MYSQL *mysql)

4. 执行查询

调用mysql_query()来执行SQL语句,如果语句中包含二进制数据,则需要调用mysql_real_query().

int mysql_query(MYSQL *mysql, const char *stmt_str)
int mysql_real_query(MYSQL *mysql, const char *stmt_str, unsigned long length)

若执行的是UPDATE, DELETEINSERT语句,则可通过mysql_affected_rows()获知受影响的记录数。

my_ulonglong mysql_affected_rows(MYSQL *mysql)

还可以通过mysql_insert_id()来获取由最近的UPDATEINSERT语句生成的自增值。

my_ulonglong mysql_insert_id(MYSQL *mysql)

若执行的是SELECT语句,则有两种方式来获取结果集。

一种方式是通过mysql_store_result()将整个结果集全部取回来。

MYSQL_RES *mysql_store_result(MYSQL *mysql)

另一种方式则是调用mysql_use_result()初始化获取操作,但暂时不取回任何记录。

MYSQL_RES *mysql_use_result(MYSQL *mysql)

然后通过mysql_fetch_row()来访问每一条记录。

MYSQL_ROW mysql_fetch_row(MYSQL_RES *result)

若先前调用的是mysql_store_result(), 则直接在本地访问记录;若先前调用的是mysql_use_result(), 则此时才到服务器上去获取记录。

当处理完结果集后,调用mysql_free_result()来释放它所占的内存。

void mysql_free_result(MYSQL_RES *result)

此外,可以调用mysql_errno()mysql_error()来获知最近执行的API函数的错误代码和错误信息。

unsigned int mysql_errno(MYSQL *mysql)
const char *mysql_error(MYSQL *mysql)

5. 预处理语句(Prepared Statements)

MySQL C API还提供了另一种方式来执行SQL语句,即先预处理(prepare)再执行(execute). 对于多次执行的SQL语句,该方式可以提高其执行效率。具体步骤如下:

1. 调用mysql_stmt_init()创建语句句柄,该句柄在随后的函数调用中都要用到。

MYSQL_STMT *mysql_stmt_init(MYSQL *mysql)

2. 调用mysql_stmt_prepare()对SQL语句进行预处理

int mysql_stmt_prepare(MYSQL_STMT *stmt, const char *stmt_str, unsigned long length)

3. 如果SQL语句中有参数,则需要调用mysql_stmt_bind_param()进行参数绑定。

my_bool mysql_stmt_bind_param(MYSQL_STMT *stmt, MYSQL_BIND *bind)

如果参数的类型为TEXTBLOB, 并且数据量很大,可以调用mysql_stmt_send_long_data()来向服务器发送数据。

my_bool mysql_stmt_send_long_data(MYSQL_STMT *stmt, unsigned int parameter_number, const char *data, unsigned long length)

4. 调用mysql_stmt_execute()来执行查询。

int mysql_stmt_execute(MYSQL_STMT *stmt)

5. 若查询不产生结果集,可以调用mysql_stmt_affected_rows()my_ulonglong mysql_stmt_insert_id(MYSQL_STMT *stmt)来获得被改变的记录数和生成的自增值。

my_ulonglong mysql_stmt_affected_rows(MYSQL_STMT *stmt)
my_ulonglong mysql_stmt_insert_id(MYSQL_STMT *stmt)

否则,执行mysql_stmt_bind_result()对结果集中的字段进行绑定。

my_bool mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)

6. 调用mysql_stmt_fetch()来逐行获取结果集中的记录。

int mysql_stmt_fetch(MYSQL_STMT *stmt)

在调用mysql_stmt_fetch()之前,还可以执行mysql_stmt_store_result()将结果集预先缓存到本地。

int mysql_stmt_store_result(MYSQL_STMT *stmt)

7. 重复步骤3-6, 每次使用不同的实参来执行查询。

8. 调用mysql_stmt_close()关闭句柄,释放资源

my_bool mysql_stmt_close(MYSQL_STMT *)

此外,可以调用mysql_stmt_errno()mysql_stmt_error()来获知最近执行的预处理语句API函数的错误代码和错误信息。

unsigned int mysql_stmt_errno(MYSQL_STMT *stmt)
const char *mysql_stmt_error(MYSQL_STMT *stmt)

6. 参考

"MySQL Reference Manual" Chapter 27 Section 2

ItemToDoForm
TopicClassification? ItemDone?
ToDoBy? ZhengYi
DueDate? 2008/07/03
Priority Normal
Intro 研究如何使用MySQL的C API
Plan 从项目开发应验中进行总结
ResearchMethod? 从项目开发应验中进行总结
WorkProducts? 本Wiki
Summary 可在需要的时候使用,比如在Apache C Handler中使用

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多