一、连接MYSQL
在使用C语言操作MYSQL数据库之前,需要先与数据库建立连接,下面是建立连接需要用到的函数(按使用顺序),只需要将函数例程跟着过一遍,我们的C程序就成功连接到我们的数据库了。(附函数参数介绍)
连接实例
int main()
{
MYSQL mysql;
if(mysql_init(&mysql) == NULL) //初始化句柄mysql
{
printf("%d : error : %s\n", __LINE__, mysql_error(&mysql));
exit(1);
}
if (mysql_library_init(0, NULL, NULL) != 0) //初始化mysql数据库
{
fprintf(stderr, "could not initialize MySQL client library\n");
exit(1);
}
if (NULL == mysql_real_connect
(&mysql,
"127.0.0.1",
"root",
"**********",
"testdb",
0,
NULL,
0)
) //与mysql服务器建立连接
{
printf("%d : error : %s\n", __LINE__, mysql_error(&mysql));
exit(1);
}
if(mysql_set_character_set(&mysql, "utf8") != 0) //设置中文字符集
{
printf("%d : error : %s\n", __LINE__, mysql_error(&mysql));
exit(1);
}
printf("connect success!\n");
//
//中间部分为程序的主题部分
//
mysql_close(&mysql);
mysql_library_end();
return 0;
}
1.MYSQL *mysql_init(MYSQL *mysql)
分配或初始化一个适用于 mysql_real_connect() 的 MYSQL 对象。 如果 mysql 是 NULL 指针,则该函数分配、初始化并返回一个新对象。 否则,初始化对象并返回对象的地址。 如果 mysql_init() 分配了一个新对象,则在调用 mysql_close() 关闭连接时将其释放。
返回值:
一个初始化的 MYSQL* 处理程序。 如果没有足够的内存来分配新对象,则为 NULL。
使用实例:
MYSQL mysql;
if(mysql_init(&mysql) == NULL)
{
printf("%d : error : %s\n", __LINE__, mysql_error(&mysql));
exit(1);
}
2.int mysql_library_init(int argc,char **argv,char **groups)
在非多线程环境中,mysql_init() 根据需要自动调用 mysql_library_init()。 但是,mysql_library_init() 在多线程环境中不是线程安全的,因此 mysql_init() 也不是线程安全的。 在调用 mysql_init() 之前,要么在产生任何线程之前调用 mysql_library_init(),要么使用互斥锁来保护 mysql_library_init() 调用。 这应该在任何其他客户端库调用之前完成。
也就是说,这个函数在单线程的程序中不是必须的;但是在我的聊天室中用到了多线程,因此需要调用这个函数。
argc、argv 和 groups 参数未使用。 在较旧的 MySQL 版本中,它们用于链接到不再支持的嵌入式服务器的应用程序。 现在调用应该写成 mysql_library_init(0, NULL, NULL)。
返回值:
成功为零。 如果发生错误,则非零。
使用实例
if (mysql_library_init(0, NULL, NULL) != 0)
{
fprintf(stderr, "could not initialize MySQL client library\n");
exit(1);
}
3. MYSQL *mysql_real_connect()
mysql_real_connect() 尝试建立与主机上运行的 MySQL 服务器的连接。 在执行任何其他需要有效 MYSQL 连接处理程序结构的 API 函数之前,客户端程序必须成功连接到服务器。
由于这个函数的参数过多,故将函数原型放在下面:
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 *mysql
这里的mysql就是之前mysql_init()初始化的句柄
-
const char *host
host 的值可以是主机名或 IP 地址,一般我们连接自己主机上的数据库,就写"127.0.0.1"
-
const char *user
user 参数包含用户的 MySQL 登录 ID,一般都为"root"
-
const char *passwd
passwd 参数包含用户的密码
-
const char *db
db 是数据库名称
-
unsigned int port
该值用作 TCP/IP 连接的端口号
-
const char *unix_socket
我们一般用NULL
-
unsigned long client_flag
client_flag 的值通常为 0
关于本函数,如果想了解更多更详细的内容,可以参考MYSQL文档
使用实例:
if (NULL == mysql_real_connect
(&mysql,
"127.0.0.1",
"root",
"**********", //这里输自己的密码
"testdb",
0,
NULL,
0)
)
{
printf("%d : error : %s\n", __LINE__, mysql_error(&mysql));
exit(1);
}
4. int mysql_set_character_set(MYSQL *mysql,const char *csname)
设置默认字符集,这里我们需要设置中文字符集,不然会出现乱码
返回值:
成功为零。 如果发生错误,则非零
使用实例
if(mysql_set_character_set(&mysql, "utf8") != 0)
{
printf("%d : error : %s\n", __LINE__, mysql_error(&mysql));
exit(1);
}
5.void mysql_close(MYSQL *mysql)
在主线程的最后不要忘记断开与MYSQL的连接
6.mysql_library_end(void)
为避免在应用程序使用库完成后(例如,关闭与服务器的连接后)发生内存泄漏,请务必显式调用 mysql_library_end()。 这使得可以执行内存管理来清理和释放库使用的资源。
使用实例
mysql_close(&mysql);
mysql_library_end();
return 0;
二、使用MYSQL
在使用C语言操作MYSQL的时候,最重要的还是MYSQL的基本语法。因为使用C语言操作MYSQL的时候,不过是把sql的语法去掉分号后放到字符数组里,再作为参数让函数去执行。
使用实例
int ret;
char query_str[BUFSIZE];
MYSQL mysql;
MYSQL *res;
MYSQL row;
strcpy(query_str, "select * from UserData");
ret = mysql_real_query(&mysql, query_str, strlen(query_str))
if(ret != 0)
{
printf("%d : error : %s\n", __LINE__, mysql_error(&mysql));
exit(1);
}
res = mysql_store_result(&mysql);
if(res == NULL)
{
//如果mysql_error()返回NULL的话,证明没有错误发生
if(strcmp(mysql_error(&mysql), "") != 0)
{
printf("%d : error : %s\n", __LINE__, mysql_error(&mysql));
exit(1);
}
}
//row(MYSQL_ROW)作为一个二级指针,我们在使用时要注意数组越界问题
while(row = mysql_fetch_row(res))
{
//...
}
1.int mysql_real_query(MYSQL *mysql, const char *stmt_str, unsigned long length)
mysql_real_query() 执行 stmt_str 指向的 SQL 语句,字符串长度字节长。 通常,字符串必须由单个 SQL 语句组成,没有终止分号或 \g。 如果启用了多语句执行,则字符串可以包含多个用分号分隔的语句。
返回值
成功为零。 如果发生错误,则非零。
2.MYSQL_RES *mysql_store_result(MYSQL *mysql)
得到MYSQL_RES这个句柄。
mysql_store_result()用来获得上一个语句产生的结果集,比所说select、show语句产生的搜索结果,但如果上一个语句没有产生结果集,那么函数返回NULL(注意这个NULL要与发生错误时返回的NULL作区分)。
返回值
指向带有结果的 MYSQL_RES 结果结构的指针。 如果语句未返回结果集或发生错误,则为 NULL。 要确定是否发生错误,请检查 mysql_error() 是否返回非空字符串、mysql_errno() 是否返回非零或 mysql_field_count() 是否返回零。
在得到MYSQL_RES *这个句柄之后,我们就可以知道有关这个数据表的所有信息。
(1).mysql_num_rows(MYSQL_RES *res)
(2).mysql_num_fields(MYSQL_RES *res)
这两个函数分别可以得到数据表中的行数和列数,比较简单,这里不细说。具体可以参考MYSQL文档
3.MYSQL_ROW mysql_fetch_row(MYSQL_RES *res)
检索结果集的下一行
如果我们想要打印出整个数据表的话,可以这样使用:
int i;
int fields;
fields = mysql_num_fields(res); //获得数据表的列数
while(row = mysql_fetch_row(res))
{
for(i=0; i<fields; i++)
{
printf("%-20s", row[i]);
}
printf("\n");
}
很重要的一个函数sprintf()
在C语言操作数据库时,sprintf()函数可以很方便的帮我们组装好一个语句:
sprintf(query_str, "select * from UserData \
where username = \"%s\"", username);
程序封装
在项目中,我们可能会频繁的使用MYSQL,为了提高编程效率(频繁的对没有结果集的sql语句调用mysql_store_result()并不会导致显著的性能下降),我们可以把常用的MYSQL函数封装一下:
对于有结果集的sql语句,我们可以用返回的句柄res对结果进行操作。
MYSQL_RES *my_real_query(MYSQL *mysql, MYSQL_RES *res, char *q, int line)
{
int ret;
char query_str[BUFSIZE];
strcpy(query_str, q);
ret = mysql_real_query(mysql, query_str, strlen(query_str));
if(ret != 0)
{
printf("%d : error : %s\n", line, mysql_error(mysql));
exit(1);
}
res = mysql_store_result(mysql);
if(res == NULL)
{
if(strcmp(mysql_error(mysql), "") != 0)
{
printf("%d : error : %s\n", line, mysql_error(mysql));
exit(1);
}
}
return res;
}
总结
在进行聊天室项目的时候需要用到MYSQL,现在两周时间过去了,我的聊天室项目也已经基本完成了,这里想记录一下在聊天室项目中非常重要的一个工具——MYSQL。
由于我此前从未接触过MYSQL,在项目进行过程中也基本都是现学现用,关于MYSQL的使用我还只是刚入门,希望这篇博客可以给大家在初次接触MYSQL的时候提供一点引导。