c++在vs2010中操作Mysql的讲解

来源:互联网 发布:关于大数据的论文 编辑:程序博客网 时间:2024/05/19 03:29

1.vs2010中mysql的构建

首先你需要mysql安装目录下的include文件夹和lib文件夹,并保证lib里面的文件完整(libmysql.dll和libmysql.lib均存在),没有的 点击这里 下载这两个文件夹,下载后直接将这两个文件夹解压放在你记得住的地方(这里我们放在了d:\mysqlc下面,分别是d:\mysqlc\include,d:\mysqlc\lib),然后打开vs2010做以下操作

右键点击你的项目名称,选择属性,分别在”c/c++”->常规,”连接器”->常规 的“附加包含目录”直接填入“d:\mysqlc\include;d:\mysqlc\lib”,也可以自己点开一个一个填写,如图(图中所示我是本机配置,请忽略):

QQ图片20130815163758

然后在 “连接器”->输入中 的 “附加依赖项”填入:libmysql.lib ,如图:

QQ图片20130815163758

然后呢,还需要一部,复制“d:\mysqlc\lib\libmysql.dll”到“c:\windows”下面,不然待会运行,会提示找不到libmysql.dll的错误

到这里我们就构建好了,这里我们先来看下代码,之后再详细讲解c++操作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
36
// test.cpp : 定义控制台应用程序的入口点 主文件入口
//
 
#include "stdafx.h"
#include "winsock.h"
#include "mysql.h"
using namespace std ;
 
void _tmain ( int argc , _TCHAR* argv [ ] )
{
     MYSQL * mysql ;     
     mysql = mysql_init ( NULL ) ;     
     char * sql = "select pid,title from posts" ;
     MYSQL_RES * result ;
     MYSQL_ROW row ;
     int r , num ;
     if ( mysql_real_connect ( mysql , "localhost" , "root" , "root" , "maijiawo" , 3306 ,NULL , 0 ) ) {
         mysql_set_character_set ( mysql , "gbk" ) ;
         if ( ! mysql_query ( mysql , sql ) ) {
             result = mysql_store_result ( mysql ) ;
             if ( result == NULL )
                 return ;
             num = mysql_num_fields ( result ) ;             
             unsigned long * lengths = mysql_fetch_lengths ( result ) ;
             while ( row = mysql_fetch_row ( result ) ) {
                 for ( r = 0 ; r < num ; r ++ ) {
                     cout << row [ r ] << ' ' ;
                 }
                 cout << endl ;
             }
             mysql_free_result ( result ) ;
         }
         mysql_close ( mysql ) ;
 
     }
}

别忘了在stdafx.h中加入这句:

#include <iostream>

现在我们来详细分析下相关函数,比较详细,慢慢看

2. Mysql连接的mysql结构

我们 在用mysql的c API时,用到最多的就是MYSQL结构了。毫无疑问这个结构是mysql c/c++编程的核心了。

以下是该结构的定义:

typedef struct st_mysql {

NET net;                                                           /* 网络连接参数 */

gptr connector_fd;                                          /* 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; // the field info

MEM_ROOT field_alloc; // the field memory

my_bool free_me; /* If free in mysql_close */

my_bool reconnect; /* set to 1 if automatic reconnect */

struct st_mysql_options options; //option

char        scramble_buff[9]; // ???

struct charset_info_st *charset; // charset info.

unsigned int  server_language; // server language/

} MYSQL;

以下是net的定义,这个结构被用来进行网络读写:

typedef struct st_net {

Vio* vio;

my_socket fd; /* For Perl DBI/dbd */

int fcntl;

unsigned char *buff,*buff_end,*write_pos,*read_pos;

char last_error[MYSQL_ERRMSG_SIZE];

unsigned int last_errno,max_packet,timeout,pkt_nr;

unsigned char error;

my_bool return_errno,compress;

my_bool no_send_ok; /* needed if we are doing several

queries in one command ( as in LOAD TABLE … FROM MASTER ),

and do not want to confuse the client with OK at the wrong time

*/

unsigned long remain_in_buf,length, buf_length, where_b;

unsigned int *return_status;

unsigned char reading_or_writing;

char save_char;

} NET;

我们在进行mysql连接以及查询时,MYSQL这个结构被用做传送信息的载体。

需要经常用到MYSQL结构的cAPI:

mysql_connect();

mysql_real_connect();

mysql_query();

mysql_store_result();

mysql_use_result();

mysql_error()

大家有兴趣可以看看这几个函数的实现,会有意想不到的收获!

3. c++操作mysql :连接

c++连接mysql的主要是通过mysql的c API来实现 。

连接的API有两个,下面会分别描述:

1.  mysql_connect()

(原型)ProtoType:   MYSQL *mysql_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd)

描述:

该函数已过时。最好使用mysql_real_connect()取而代之。

mysql_connect()试图建立与运行在主机(远程主机也可以)上的MySQL数据库引擎的连接。在能够执行任何其他API函数之前,必须先调用mysql_connect(),而且返回成功。但mysql_get_client_info()例外。

这些参数的意义与mysql_real_connect()的对应参数的意义相同,差别在于连接句柄可以为NULL。在这种情况下,C API将自动为连接结构分配内存,并当调用mysql_close()时释放分配的内存。该方法的缺点是,如果连接失败,你无法检索错误消息。要想从mysql_errno()或mysql_error()获得错误消息,必须提供有效的MYSQL指针。

返回值: NULL表示失败。反之成功。

2.  mysql_real_connect()

原型:

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_real_connect()尝试与运行在主机上的MySQL数据库引擎建立连接。在你能够执行需要有效MySQL连接句柄结构的任何其他API函数之前,mysql_real_connect()必须被调用并返回成功。

参数说明:

·         第1个参数应是已有MYSQL结构的地址。调用mysql_real_connect()之前, 必须调用mysql_init()来初始化MYSQL结构 。

通过mysql_options()调用,可更改多种连接选项。

·

host的值必须是主机名或IP地址。如果host是NULL或字符串”localhost”,连接将被视为与本地主机的连接。如果操作系统支持套接字(Unix)或命名管道(Windows),将使用它们而不是TCP/IP连接到服务器。

·

user参数包含用户的MySQL登录ID。如果user是NULL或空字符串”",用户将被视为当前用户。在UNIX环境下,它是当前的登录名。在Windows ODBC下,必须明确指定当前用户名。请参见 26.1.9.2节,“在Windows上配置MyODBC DSN” 。

·

passwd参数包含用户的密码。如果passwd是NULL,仅会对该用户的(拥有1个空密码字段的)用户表中的条目进行匹配检查。这样,数据库管理员就能按特定的方式设置MySQL权限系统,根据用户是否拥有指定的密码,用户将获得不同的权限。

注释: 调用mysql_real_connect()之前,不要尝试加密密码,密码加密将由客户端API自动处理。

·

db是数据库名称。如果db为NULL,连接会将默认的数据库设为该值。 当你不想连接特定数据库时,可以指定db为NULL

·

如果“port”不是0,其值将用作TCP/IP连接的端口号。注意,“host”参数决定了连接的类型。port为0的话,使用mysql的默认tcp/ip端口3306.

·

如果unix_socket不是NULL,该字符串描述了应使用的套接字或命名管道。注意,“host”参数决定了连接的类型。

 

·client_flag的值通常为0,但是,也能将其设置为下述标志的组合,以允许特定功能:

 

标志名称标志描述CLIENT_COMPRESS使用压缩协议。CLIENT_FOUND_ROWS返回发现的行数(匹配的),而不是受影响的行数。CLIENT_IGNORE_SPACE允许在函数名后使用空格。使所有的函数名成为保留字。CLIENT_INTERACTIVE关闭连接之前,允许interactive_timeout(取代了wait_timeout)秒的不活动时间。客户端的会话wait_timeout变量被设为会话interactive_timeout变量的值。CLIENT_LOCAL_FILES允许LOAD DATA LOCAL处理功能。CLIENT_MULTI_STATEMENTS通知服务器,客户端可能在单个字符串内发送多条语句(由‘;’隔开)。如果未设置该标志,将禁止多语句执行。CLIENT_MULTI_RESULTS通知服务器,客户端能够处理来自多语句执行或存储程序的多个结果集。如果设置了CLIENT_MULTI_STATEMENTS,将自动设置它。CLIENT_NO_SCHEMA禁止 db_name.tbl_name.col_name 语法。它用于ODBC。如果使用了该语法,它会使分析程序生成错误,在捕获某些ODBC程序中的缺陷时,它很有用。CLIENT_ODBC客户端是ODBC客户端。它将 mysqld 变得更为ODBC友好。CLIENT_SSL使用SSL(加密协议)。该选项不应由应用程序设置,它是在客户端库内部设置的。
示例代码:
1
2
3
4
5
6
mysql_init ( & mysql ) ;
 
if ( ! mysql_real_connect ( & mysql , "host" , "user" , "passwd" , "database" , 0 , NULL ,0 ) )
{ //判断连接是否失败。
     printf ( "Failed to connect to database: Error: %s/n" ,    mysql_error ( & mysql ) ) ;
}

 

连接成功后,你就可以执行其他操作了。

mysql_connect和mysql_real_connect的区别:
1. mysql_connect不需要调用mysql_init来初始化连接句柄.但是mysql_real_connect需要。
2. mysql_connect只能指定host,user,password, database四个参数,无法指定特定端口,使用命名管道。只能使用默认的TCP/IP连接。默认端口只能是3306
3. mysql_connect在实现里调用了mysql_real_connect.是对其的封装。
我们可以从库的实现文件libmysql.c看到mysql_connect()函数的实现:
MYSQL * STDCALL
mysql_connect(MYSQL *mysql,const char *host, const char *user, const char *passwd)
{
  MYSQL *res;
  mysql=mysql_init(mysql); /* Make it thread safe */
  {
    DBUG_ENTER(“mysql_connect”);
   if (!(res = mysql_real_connect(mysql, host, user, passwd, null, 0, null, 0)))
   {
      if (mysql->free_me)
my_free((gptr) mysql,MYF(0));
    }
    DBUG_RETURN(res);
  }
}
mysql_real_connect的实现就很长很复杂了。在此不贴出,有需要的同学可通过向我索取。
通过这两个函数,大家想必对mysql的连接都更多的了解了。在实际运用过程中,这两个函数已经够用了。还有需要用到的是
mysql_options来通过更改连接选项。
备注:
本文函数说明来自mysql5.1官方文档。
所需资料均来自mysql。

4. c++操作mysql :查询

讲完了连接,接着就讲查询了。

mysql的执行和查询都是使用一下2个接口:

1. mysql_query(MYSQL* mysql, const char* sql);

2. int mysql_real_query(MYSQL *mysql, const char *query, unsigned long length);

一下就分别描述这两个函数:

1.  mysql_query()

int mysql_query(MYSQL *mysql, const char *query)

 

描述

执行由“Null终结的字符串”查询指向的SQL查询。正常情况下,字符串必须包含1条SQL语句, 而且不应为语句添加终结分号(‘;’)或“/g”。如果允许多语句执行 ,字符串可包含多条由分号隔开的语句。但是连接的时候必须指定CLIENT_MULTI_STATEMENTS选项。

mysql_query()不能用于包含二进制数据的查询,应使用mysql_real_query()取而代之(二进制数据可能包含字符‘/0’,mysql_query()会将该字符解释为查询字符串结束)。

如果希望了解查询是否应返回结果集,可使用mysql_field_count()进行检查。请参见25.2.3.22节,“mysql_field_count()” 。

返回值

如果查询成功,返回0。如果出现错误,返回非0值。

2.  mysql_real_query()

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

描述

执行由“query”指向的SQL查询,它应是字符串长度字节“long”。正常情况下,字符串必须包含1条SQL语句, 而且不应为语句添加终结分号(‘;’)或“/g” 。如果允许多语句执行,字符串可包含由分号隔开的多条语句。但是连接的时候必须指定CLIENT_MULTI_STATEMENTS选项。

对于包含二进制数据的查询,必须使用mysql_real_query()而不是mysql_query(),这是因为,二进制数据可能会包含‘/0’字符。此外,mysql_real_query()比mysql_query()快,这是因为它不会在查询字符串上调用strlen()。

如果希望知道查询是否应返回结果集,可使用mysql_field_count()进行检查 25.2.3.22节,“mysql_field_count()” 。

返回值

如果查询成功,返回0。如果出现错误,返回非0值。

如果失败,可使用mysql_error(MYSQL* mysql)看看错误信息。

使用mysql_query和mysql_real_query可以执行任何的mysql语句。不需要在语句末尾加上分号!

对于没有像select一样的查询,需要接着调用mysql_store_result或者mysql_use_result来保存结果集。

对于insert或者delete,create语句,不返回结果集的,判断返回值看看是否执行成功,然后用mysql_affected_rows函数来

查询被影响的行数。用mysql_error(MYSQL* mysql)来看错误信息

5. c++操作mysql :查询结果集

用mysql进行数据查询的时候,mysql会返回一个结果集给我们。接着我们需要调用mysql的api,从这个结果集中取得我们要的数据。

取完数据之后,需要释放这个结果集。

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;                                         // 非缓冲的时候用到

MYSQL_ROW current_row;                           //mysql_store_result时会用到。当前行

unsigned long *lengths;                                //每列的长度

MYSQL *handle;                                           // mysql_use_result会用。

my_bool eof;                                                 //是否为行尾

} MYSQL_RES;

typedef char ** MYSQL_ROW ; /* 返回的每一行的值,全部用字符串来表示*/
typedef struct st_mysql_rows {
  struct st_mysql_rows *next; /* list of rows */
  MYSQL_ROW data;
}  MYSQL_ROWS ;        //mysql的数据的链表节点。可见mysql的结果集是链表结构
typedef struct st_mysql_data {
  my_ulonglong rows;
  unsigned int fields;
  MYSQL_ROWS *data;
  MEM_ROOT alloc;
}  MYSQL_DATA ; // 数据集的结构
typedef struct st_mysql_field {
  char *name; /* Name of column */
  char *table;                                            /* Table of column if column was a field */
  char *def;                                               /* Default value (set by mysql_list_fields) */
  enum enum_field_types type;                /* Type of field. Se mysql_com.h for types */
  unsigned int length;                               /* Width of column */
  unsigned int max_length;                       /* Max width of selected set */
  unsigned int flags;                                  /* Div flags */
  unsigned int decimals;                            /* Number of decimals in field */
}  MYSQL_FIELD ;  //列信息的结构

typedef struct st_used_mem { /* struct for once_alloc */

struct st_used_mem *next; /* Next block in use */

unsigned int left; /* memory left in block  */

unsigned int size; /* Size of block */

}  USED_MEM ; //内存结构

typedef struct st_mem_root {

USED_MEM *free;

USED_MEM *used;

USED_MEM *pre_alloc;

unsigned int min_malloc;

unsigned int block_size;

void (*error_handler)(void);

}  MEM_ROOT ;  //内存结构

之所以列出这些结构,是想让大家对mysql的结果集有更清晰的认识。

以下是取得数据的相关API:

1.  . mysql_store_result()

MYSQL_RES *mysql_store_result(MYSQL *mysql)

描述

对于成功检索了数据的每个查询(SELECT、SHOW、DESCRIBE、EXPLAIN、CHECK TABLE等),必须调用mysql_store_result()或mysql_use_result() 。

对于其他查询,不需要调用mysql_store_result()或mysql_use_result(),但是如果在任何情况下均调用了mysql_store_result(),它也不会导致任何伤害或性能降低。通过检查mysql_store_result()是否返回0,可检测查询是否没有结果集(以后会更多)。

如果希望了解查询是否应返回结果集,可使用mysql_field_count()进行检查。请参见25.2.3.22节,“mysql_field_count()” 。

mysql_store_result()将查询的全部结果读取到客户端,分配1个MYSQL_RES结构,并将结果置于该结构中。

如果查询未返回结果集,mysql_store_result()将返回Null指针(例如,如果查询是INSERT语句)。

如果读取结果集失败,mysql_store_result()还会返回Null指针。通过检查mysql_error()是否返回非空字符串,mysql_errno()是否返回非0值,或mysql_field_count()是否返回0,可以检查是否出现了错误。

如果未返回行,将返回空的结果集。(空结果集设置不同于作为返回值的空指针)。

一旦调用了mysql_store_result()并获得了不是Null指针的结果,可调用mysql_num_rows()来找出结果集中的行数。

可以调用mysql_fetch_row()来获取结果集中的行,或调用mysql_row_seek()和mysql_row_tell()来获取或设置结果集中的当前行位置。

一旦完成了对结果集的操作,必须调用mysql_free_result()。

2.  mysql_use_result()

MYSQL_RES *mysql_use_result(MYSQL *mysql)

描述

对于成功检索数据的每个查询(SELECT、SHOW、DESCRIBE、EXPLAIN),必须用mysql_store_result()或mysql_use_result()。

mysql_use_result()将初始化结果集检索,但并不像mysql_store_result()那样将结果集实际读取到客户端。 它必须通过对mysql_fetch_row()的调用,对每一行分别进行检索。这将直接从服务器读取结果,而不会将其保存在临时表或本地缓冲区内,与mysql_store_result()相比,速度更快而且使用的内存也更少。 客户端仅为当前行和通信缓冲区分配内存,分配的内存可增加到max_allowed_packet字节。

另一方面,如果你正在客户端一侧为各行进行大量的处理操作,或者将输出发送到了用户可能会键入“^S”(停止滚动)的屏幕,就不应使用mysql_use_result()。这会绑定服务器,并阻止其他线程更新任何表(数据从这类表获得)。

使用mysql_use_result()时,必须执行mysql_fetch_row(),直至返回NULL值,否则,未获取的行将作为下一个检索的一部分返回 。C API给出命令不同步错误,如果忘记了执行该操作,将不能运行该命令。

不能对结果集用mysql_data_seek()、mysql_row_seek()、mysql_row_tell()、mysql_num_rows()或mysql_affected_rows(),也不应发出其他查询,直至mysql_use_result()完成为止。(但是,提取了所有行后,mysql_num_rows()将准确返回提取的行数)。

一旦完成了对结果集的操作,必须调用mysql_free_result()。

返回值

MYSQL_RES结果结构。如果出现错误,返回NULL。

3.取得一行的数据:

mysql_fetch_row()

MYSQL_ROW mysql_fetch_row(MYSQL_RES *result)

描述

检索结果集的下一行。在mysql_store_result()之后使用时,如果没有要检索的行,mysql_fetch_row()返回NULL。

在mysql_use_result()之后使用时,如果没有要检索的行或出现了错误,mysql_fetch_row()返回NULL。

结果集的列数目由mysql_num_fields(result)给出。如果行中保存了调用mysql_fetch_row()返回的值,将按照row[0]到row[mysql_num_fields(result)-1],访问这些值的指针。行中的NULL值由NULL指针指明。

可以通过调用mysql_fetch_lengths()来获得行中字段值的长度。对于空字段以及包含NULL的字段,长度为0。通过检查字段值的指针,能够区分它们。如果指针为NULL,字段为NULL,否则字段为空。

返回值

下一行的MYSQL_ROW结构。如果没有更多要检索的行或出现了错误,返回NULL。

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//假设mysql已经连接好
MYSQL_RES* result = mysql_store_result ( mysql ) ;
 
if ( result    == NULL )
   return ;
 
MYSQL_ROW row ;
unsigned int num_fields ;
unsigned int i ;
num_fields = mysql_num_fields ( result ) ;
while ( ( row = mysql_fetch_row ( result ) ) )
{
   unsigned long * lengths ;
   lengths = mysql_fetch_lengths ( result ) ;
   for ( i = 0 ; i < num_fields ; i ++ )
   {
       printf ( "[%.*s] " , ( int ) lengths [ i ] , row [ i ] ? row [ i ] : "NULL" ) ;
   }
   printf ( "/n" ) ;
}

4. 取得列的信息。

mysql_fetch_field()

 

MYSQL_FIELD *mysql_fetch_field(MYSQL_RES *result)

描述

返回采用MYSQL_FIELD结构的结果集的列。重复调用该函数,以检索关于结果集中所有列的信息。未剩余字段时,mysql_fetch_field()返回NULL。

每次执行新的SELECT查询时,将复位mysql_fetch_field(),以返回关于第1个字段的信息。调用mysql_field_seek()也会影响mysql_fetch_field()返回的字段。

如果调用了mysql_query()以在表上执行SELECT,但未调用mysql_store_result(),如果调用了mysql_fetch_field()以请求BLOB字段的长度,MySQL将返回默认的Blob长度(8KB)。之所以选择8KB是因为MySQL不知道BLOB的最大长度。应在日后使其成为可配置的。一旦检索了结果集,field->max_length将包含特定查询中该列的最大值的长度。

返回值

当前列的MYSQL_FIELD结构。如果未剩余任何列,返回NULL。

错误

无。

示例:

1
2
3
4
5
MYSQL_FIELD * field ;
while ( ( field = mysql_fetch_field ( result ) ) )
{
     printf ( "field name %s/n" , field -> name ) ;
}

5. 同4.

 mysql_fetch_fields()

MYSQL_FIELD *mysql_fetch_fields(MYSQL_RES *result)

描述

对于结果集,返回所有MYSQL_FIELD结构的数组。每个结构提供了结果集中1列的字段定义。

返回值

关于结果集所有列的MYSQL_FIELD结构的数组。

示例:

1
2
3
4
5
6
7
8
9
10
unsigned int num_fields ;
unsigned int i ;
MYSQL_FIELD * fields ;
 
num_fields = mysql_num_fields ( result ) ;
fields = mysql_fetch_fields ( result ) ;
for ( i = 0 ; i < num_fields ; i ++ )
{
   printf ( "Field %u is %s/n" , i , fields [ i ] . name ) ;
}

 

6.

 mysql_free_result()

 

void mysql_free_result(MYSQL_RES *result)

描述

释放由mysql_store_result()、mysql_use_result()、mysql_list_dbs()等为结果集分配的内存。完成对结果集的操作后,必须调用mysql_free_result()释放结果集使用的内存。

 

释放完成后,不要尝试访问结果集。

最后也别忘了 mysql_close(mysql) !

返回值

无。

永远记得要释放结果集!!!

0 0
原创粉丝点击