MySql C API查询过程介绍

MySql C API查询过程介绍


2005-3-28 keep_thinking     


一、概述
MySql的C API的查询主要分成两类,字符串组成的sql语句的查询,包含二进制数据的sql语句的查询。第一类查询只需要传入sql语句给查询函数即可,第二类查询不但需要传递sql语句,还要传入sql语句的长度。显然第一类查询是不需要传递长度的,因为系统知道NULL表示字符串的终结。而第二种查询必须传递sql语句的长度,因为含有二进制的数据的sql语句中有可能会有值为NULL的字节,如果还是按照第一种的策略来取查询语句的长度,显然会存在将其中途截断的危险。
下面分别对第一类查询和第二类查询各举一个例子。

二、传入不含二进制数据的sql语句的查询
首先请粗略的看一遍代码,下面进行详细地分析。

void db_do_query(MYSQL *db, const char *query)

{

         if (mysql_query(db, query) != 0)

                   goto err;

         if (mysql_field_count(db) > 0)

         {

                  MYSQL_RES   *res;

                  MYSQL_ROW    row;

                   int num_fields;

                   if (!(res = mysql_store_result(db)))

                            goto err;

                  num_fields = mysql_num_fields(res);

                   while ((row = mysql_fetch_row(res)))

                   {

                            for (int i=0; i < num_fields; i++)

                                     if(row==NULL)

                                              cout<<"NULL";

                                     else

                                              cout<<row[i]<<' ';

                            cout<<endl;

                   }

                  mysql_free_result(res);

         }

         else

                  (void)printf("Affected rows: %lld/n", mysql_affected_rows(db));

         return;

err:

         die(db, "db_do_query failed: %s [%s]", mysql_error(db), query);

}
对于不包含二进制数据的查询,最核心的就是上面这一段代码
1. mysql_query是MySql的查询函数它需要2个参数,一个是指向MySQL结构类型的指针,另一个是包含sql查询语句的字符串。mysql_query函数本身并不能返查询后的结果,要得到结果需要再调用另一个函数mysql_store_result。
2. 函数mysql_store_result的返回值是一个指向MYSQL_RES结构的指针,该指针指向了查询结果。但是还是不能直接通过MYSQL_RES打印出每一个数据项。
3. 需要调用mysql_fetch_row函数来得到指向每一个查询结果的数据项的指针,该函数需要反复调用,每调用一次就返回一行的指针。在上述代码中,用循环语句反复调用的,直到结果表的末尾。另外你也可以使用mysql_num_rows函数返回查询结果集有多少行数据。
4. mysql_fetch_row函数返回的结果是一个MYSQL_ROW结构的指针,该指针可以看成一个字符串数组,该数组成存放着查询结果的一行的每个域的值,可以通过中括号运算符索引。
5. 这时候还有一个问题,究竟得到的查询结果表有多少个域呢?,这个值可以通过函数mysql_num_fields得到。

三、传入含有二进制数据的sql语句的查询
先看下面的代码,注意与上面列出的传入字符串数据的sql语句的查询的源代码不同的地方。
void db_do_real_query(MYSQL *db, const char *query, unsigned int len)

{

         if (mysql_query(db, query) != 0)

                   goto err;

         if (mysql_field_count(db) > 0)

         {

                  MYSQL_RES   *res;

                  MYSQL_ROW    row;

                   int num_fields;

                   ulong* lengths; //用来存储结果集的列数据的长度

                   if (!(res = mysql_store_result(db)))

                            goto err;

                  num_fields = mysql_num_fields(res);

                   while ((row = mysql_fetch_row(res)))

                   {

                            lengths = mysql_fetch_lengths(res);

                            for (int i=0; i < num_fields; i++)

                                     if(row==NULL)

                                              cout<<"NULL";

                                     else

                                               //得到的数据地址是row[i],长度是lengths[i]

                            cout<<endl;

                   }

                  mysql_free_result(res);

         }

         else

                  (void)printf("Affected rows: %lld/n", mysql_affected_rows(db));

         return;

err:

         die(db, "db_do_query failed: %s [%s]", mysql_error(db), query);

}

不同的地方只有两个:
1. 函数需要传入查询的sql语句的长度,原因上文已述。
2. 就是需要一个ulong型的指针来存储结果集数据的宽度。

四、另外两个问题
1.关于mysql_store_result和两个mysql_use_result函数,这两个函数都是得到查询结果集的函数,例子程序中都是用的第一个,可以换成第二个。这两个函数的不同之处在于,第一个函数会返回整个的结果集,第二个是逐个返回结果集的元组,当fetch的时候才返回后面的。
2.由于mysql的C API函数用到许多mysql自定义的类型,直接将其用到MFC的程序中是有问题的。或许是mysql的头文件和stdafx.h不兼容。解决的办法是编写一个dll文件用MFC编写的程序调用。显然dll也是不能用MFC写的,需要用SDK来写。

附录、MySQL C 变量类型
以下变量类型在MySQL的库当中定义。我们需要这些变量是为了使用MySQL的函数。这些变量有详细的解释,但是这些解释对于写代码来说并不重要。
MYSQL结构,一开始要定义一个指向该结构类型的指针,在MySql后继的所有关键函数,包括初始化、查询、结束查询都要用到这个指针作为参数
结构的定义:
typedef struct st_mysql {
 NET           net;            /* Communication parameters */
 gptr          connector_fd;   /* ConnectorFd for SSL */
 char          *host,*user,*passwd,*unix_socket,
  *server_version,*host_info,*info,*db;
 unsigned int  port,client_flag,server_capabilities;
 unsigned int  protocol_version;
 unsigned int  field_count;
 unsigned int  server_status;
 unsigned long thread_id;      /* Id for connection in server */
 my_ulonglong affected_rows;
 my_ulonglong insert_id;       /* id if insert on table with NEXTNR */
 my_ulonglong extra_info;              /* Used by mysqlshow */
 unsigned long packet_length;
 enum mysql_status status;
 MYSQL_FIELD   *fields;
 MEM_ROOT      field_alloc;
 my_bool       free_me;        /* If free in mysql_close */
 my_bool       reconnect;      /* set to 1 if automatic reconnect */
 struct st_mysql_options options;
 char          scramble_buff[9];
 struct charset_info_st *charset;
 unsigned int  server_language;
} MYSQL;

MYSQL_RES用来表示查询结果返回值的结构,
typedef struct st_mysql_res {
 my_ulonglong row_count;
 unsigned int  field_count, current_field;
 MYSQL_FIELD   *fields;
 MYSQL_DATA    *data;
 MYSQL_ROWS    *data_cursor;
 MEM_ROOT      field_alloc;
 MYSQL_ROW     row;            /* If unbuffered read */
 MYSQL_ROW     current_row;    /* buffer to current row */
 unsigned long *lengths;       /* column lengths of current row */
 MYSQL         *handle;        /* for unbuffered reads */
 my_bool       eof;            /* Used my mysql_fetch_row */
} MYSQL_RES;

其他数据类型和函数的说明参考MySQL参考手册。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值