c 使用mysql输出语句_使用C语言访问MySQL数据 —— 执行SQL语句(2)

本文介绍了如何使用C语言执行MySQL的SQL语句,包括UPDATE、DELETE、INSERT以及SELECT。详细讲解了mysql_store_result和mysql_use_result的区别和用法,以及如何处理和释放查询结果。
摘要由CSDN通过智能技术生成

2011-05-15 wcdj

(一) 不返回数据的SQL语句 —— UPDATE、DELETE 和 INSERT

(二) 发现插入的内容

(三) 返回数据的语句

(1) 一次提取所有数据的函数

(2) 一次提取一行数据的函数

(三) 返回数据的语句

SQL最常见的用法当然是提取数据而不是插入或更新数据。数据是使用SELECT语句提取的。

说明 :MySQL也支持使用SQL语句SHOW、DESCRIBE和EXPLAIN来返回结果,但我们不会在这里涉及它们。按照惯例,手册中包含了对这些语句的解释。

在C应用程序中提取数据一般需要下面4个步骤 :

【1】执行查询

【2】提取数据

【3】处理数据

【4】必要的清理工作

使用mysql_query来发送SQL语句,然后使用mysql_store_result或mysql_use_result来提取数据,接着,使用一些列mysql_fetch_row调用来处理数据。最后,使用mysql_free_result释放查询占用的内存资源。

说明 :mysql_use_result和mysql_store_result的区别 :主要在于,你是想一次返回一行数据,还是一次返回所有的结果。当你预计结果集比较小时,后者会更加合适。

(1) 一次提取所有数据的函数

可以使用mysql_store_result在一次调用中从SELECT(或其他返回数据的语句)中提取所有数据:

MYSQL_RES *mysql_store_result( MYSQL *connection );

你需要在成功调用mysql_query之后使用此函数。这个函数将立刻保存在客户端中返回的所有数据。它返回一个指向结果集结构的指针,如果失败则返回NULL。

在mysql_store_result调用成功之后,你需要调用mysql_num_rows来得到返回记录的数目,我们希望这是个正数,但是如果没有返回行,这个值将是0。

my_ulonglong mysql_num_rows( MYSQL_RES *result );

这个函数接受由mysql_store_result返回的结果结构,并返回结果集中的行数。如果mysql_store_result调用成功,mysql_num_rows将始终都是成功的。

注意 :

如果碰巧使用的是一个特别 的数据集,那么最后提取小一些、更容易管理的信息块,因为这将更快地将控制权返回给应用程序,并且不会占用大量的网络资源。具体参考mysql_use_result的用法。

现在,你可以使用mysql_fetch_row来处理它,也可以使用mysql_data_seek、mysql_row_seek和mysql_row_tell在数据集中来回移动。

[1] mysql_fetch_row

这个函数从使用mysql_store_result得到的结果结构中提取一行,并把它放到一个行结构中。当数据用完或发生错误时返回NULL。

MYSQL_ROW mysql_fetch_row( MYSQL_RES *result );

[2] mysql_data_seek

这个函数用来在结果集中进行跳转,设置将会被下一个mysql_fetch_row操作返回的行。参数offset的值是一个行号,它必须在0到结果集总行数减1的范围内。传递0将会导致下一个mysql_fetch_row调用返回结果集中的第一行。

void mysql_data_seek( MYSQL_RES *result, my_ulonglong offset );

[3] mysql_row_tell

这个函数返回一个偏移值,它用来表示结果集中的当前位置。它不是行号,你不能把它用于mysql_data_seek。

MYSQL_ROW_OFFSET mysql_row_tell( MYSQL_RES *result );

[4] mysql_row_seek

可以在mysql_row_seek中使用mysql_row_tell的返回值。

MYSQL_ROW_OFFSET mysql_row_seek( MYSQL_RES *result, MYSQL_ROW_OFFSET offset );

这将在结果集中移动当前位置,并返回之前的位置。

注意:

这对函数对于在结果集中的已知点之间的移动非常有用。但请小心不要混淆了由row_tell和row_seek使用的偏移量和data_seek使用的行号。否则,结果将变得不可预知。

[5] mysql_free_result

void mysql_free_result( MYSQL_RES *result );

完成了对数据集的操作后,你必须总是调用此函数来让MySQL库清理它分配的对象。

例子:

选择所有年龄大于100的记录。

select1.c

使用用户wcdj登录mysql

$ mysql -u wcdj -p newdatabase

Enter password:

Welcome to the MySQL monitor. Commands end with ; or /g.

显示表中的所有数据

mysql> SELECT * FROM children;

#include

#include

#include "mysql.h"

MYSQL my_connection;

MYSQL_RES *res_ptr;

MYSQL_ROW sqlrow;

int main(int argc, char *argv[])

{

int res;

mysql_init(&my_connection);

if(mysql_real_connect(&my_connection, "localhost", "wcdj", "123", "newdatabase", 0, NULL, 0))

{

printf("Connection success/n");

res = mysql_query(&my_connection, "SELECT childno, fname, age FROM children WHERE age > 100");

if (res)

{

printf("SELECT error: %s/n", mysql_error(&my_connection));

}

else// ok

{

res_ptr = mysql_store_result(&my_connection);

if (res_ptr)// ok

{

printf("Retrieved %lu rows/n", (unsigned long)mysql_num_rows(res_ptr));// ok

while ((sqlrow = mysql_fetch_row(res_ptr)))

{

printf("Fetched data.../n");// ok

}

if (mysql_errno(&my_connection))

{

fprintf(stderr, "Retrive error: %s/n", mysql_error(&my_connection));

}

mysql_free_result(res_ptr);

}

}

mysql_close(&my_connection);

}

else

{

fprintf(stderr, "Connection failed/n");

if (mysql_errno(&my_connection))

{

fprintf(stderr, "Connection error %d: %s/n", mysql_errno(&my_connection),

mysql_error(&my_connection));

}

}

return EXIT_SUCCESS;

}

编译程序:

$ gcc -I/usr/include/mysql select1.c -L/usr/lib/mysql -lmysqlclient -o select1

(2) 一次提取一行数据的函数

MYSQL_RES *mysql_use_result(MYSQL *connection);

与mysql_store_result函数一样,mysql_use_result在遇到错误时也返回NULL。如果成功,它返回指向结果集对象的指针。但是,不同之处在于它未将提取的数据放到它初始化的结果集中。

注意 :

为了真正得到数据,你必须反复调用mysql_fetch_row直到提取了所有的数据。如果没有从mysql_use_result中得到所有数据,那么程序中后续的提取数据操作可能会返回遭到破坏的信息。

调用mysql_use_result和调用mysql_store_result的效果有何不同 呢?

【1】mysql_use_result的缺点

1、前者具备资源管理方面的实质性好处,但是它不能与mysql_data_seek、mysql_row_seek或mysql_row_tell一起使用,并且由于直到所有数据都被提取后才能实际生效,mysql_num_rows的使用也受到限制。

2、而且,还增加了时延,因为每个行请求和结果的返回都必须通过网络。

3、另外还存在一种可能性是,网络连接可能在操作中途失败,留给你不完整的数据。

【2】mysql_use_result的优点

但是,无论怎样,上述缺点都不会抹去mysql_use_result带来的好处:更好地平衡了网络负载,以及减少了可能非常大的数据集带来的存储开销。

例子:

这里使用mysql_use_result函数

select2.c

#include

#include

#include "mysql.h"

MYSQL my_connection;

MYSQL_RES *res_ptr;

MYSQL_ROW sqlrow;

int main(int argc, char *argv[])

{

int res;

mysql_init(&my_connection);

if(mysql_real_connect(&my_connection, "localhost", "wcdj", "123", "newdatabase", 0, NULL, 0))

{

printf("Connection success/n");

res = mysql_query(&my_connection, "SELECT childno, fname, age FROM children WHERE age > 100");

if (res)

{

printf("SELECT error: %s/n", mysql_error(&my_connection));

}

else// ok

{

//res_ptr = mysql_store_result(&my_connection);

res_ptr = mysql_use_result(&my_connection);// mysql_use_result

if (res_ptr)// ok

{

printf("Retrieved %lu rows/n", (unsigned long)mysql_num_rows(res_ptr));// ok, 0

while ((sqlrow = mysql_fetch_row(res_ptr)))

{

printf("Fetched data.../n");// ok

}

if (mysql_errno(&my_connection))

{

fprintf(stderr, "Retrive error: %s/n", mysql_error(&my_connection));

}

mysql_free_result(res_ptr);

}

}

mysql_close(&my_connection);

}

else

{

fprintf(stderr, "Connection failed/n");

if (mysql_errno(&my_connection))

{

fprintf(stderr, "Connection error %d: %s/n", mysql_errno(&my_connection),

mysql_error(&my_connection));

}

}

return EXIT_SUCCESS;

}

编译程序:

$ gcc -I/usr/include/mysql select2.c -L/usr/lib/mysql -lmysqlclient -o select2

注意 :

在提取最后一个结果之前,你仍然无法得到行数(测试,mysql_nuw_rows此时返回结果为0)。但是,通过早期和经常性的错误检查,可以使得程序调整为使用mysql_use_result变得更加容易。以这种方式编写代码可以减少许多程序后期修改带来的烦恼。

参考 :

SQL语言基本语句介绍

http://www.longen.org/s-z/details~z/SqlSentence.htm Linux 程序设计(第4版)第8章 P.293

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值