搞定linux上MySQL编程(六):C语言编写MySQL程序(结)_It_BeeCoder的博客-程序员宝宝

技术标签: 27 Linux下C语言编程  

From:http://blog.csdn.net/shallnet/article/details/46485675

        在实际应用中,我们不可能在命令行登录进数据库进行数据的查询、插入等操作,用户一般是使用一个界面良好的应用程序软件来对数据进行管理。为了方便应用程序的开发,MySQL提供了多种编程语言(C、perl、php等)的编程接口,供开发者使用。
        对于C语言来说,MySQL提供了C语言客户机库,它允许从任何C程序的内部访问MySQL数据库,客户机实现API,API定义了客户机如何建立和执行与服务器的通信。使用C语言开发MySQL项目具有更好的安全性和性能,C语言API是与MySQL一起提供的,包含在mysqlclient库文件中,用于连接和执行数据库查询。
        首先看一下MySQL为C语言操作定义的数据类型。
1. MYSQL,MYSQL结构代表一个数据库连接句柄,包含有关服务器的连接状态的信息,几乎所有函数都是用到它。其定
义如下:
  1. typedef struct st_mysql  
  2. {  
  3.   NET           net;                    /* Communication parameters */  
  4.   unsigned char *connector_fd;          /* ConnectorFd for SSL */  
  5.   char          *host,*user,*passwd,*unix_socket,*server_version,*host_info;  
  6.   char          *info, *db;  
  7.   struct charset_info_st *charset;  
  8.   MYSQL_FIELD   *fields;  
  9.   MEM_ROOT      field_alloc;  
  10.   my_ulonglong affected_rows;  
  11.   my_ulonglong insert_id;               /* id if insert on table with NEXTNR */  
  12.   my_ulonglong extra_info;              /* Not used */  
  13.   unsigned long thread_id;              /* Id for connection in server */  
  14.   unsigned long packet_length;  
  15.   unsigned int  port;  
  16.   unsigned long client_flag,server_capabilities;  
  17.   unsigned int  protocol_version;  
  18.   unsigned int  field_count;  
  19.   unsigned int  server_status;  
  20.   unsigned int  server_language;  
  21.   unsigned int  warning_count;  
  22.   struct st_mysql_options options;  
  23.   enum mysql_status status;  
  24.   my_bool       free_me;                /* If free in mysql_close */  
  25.   my_bool       reconnect;              /* set to 1 if automatic reconnect */  
  26.   
  27.   /* session-wide random string */  
  28.   char          scramble[SCRAMBLE_LENGTH+1];  
  29.   
  30.  /* 
  31.    Set if this is the original connection, not a master or a slave we have 
  32.    added though mysql_rpl_probe() or mysql_set_master()/ mysql_add_slave() 
  33.  */  
  34.   my_bool rpl_pivot;  
  35.   /* 
  36.     Pointers to the master, and the next slave connections, points to 
  37.     itself if lone connection. 
  38.   */  
  39.   struct st_mysql* master, *next_slave;  
  40.   
  41.   struct st_mysql* last_used_slave; /* needed for round-robin slave pick */  
  42.  /* needed for send/read/store/use result to work correctly with replication */  
  43.   struct st_mysql* last_used_con;  
  44.   
  45.   LIST  *stmts;                     /* list of all statements */  
  46.   const struct st_mysql_methods *methods;  
  47.   void *thd;  
  48.   /* 
  49.     Points to boolean flag in MYSQL_RES  or MYSQL_STMT. We set this flag 
  50.     from mysql_stmt_close if close had to cancel result set of this object. 
  51.   */  
  52.   my_bool *unbuffered_fetch_owner;  
  53.   /* needed for embedded server - no net buffer to store the 'info' */  
  54.   char *info_buffer;  
  55.   void *extension;  
  56. } MYSQL;  
typedef struct st_mysql
{
  NET           net;                    /* Communication parameters */
  unsigned char *connector_fd;          /* ConnectorFd for SSL */
  char          *host,*user,*passwd,*unix_socket,*server_version,*host_info;
  char          *info, *db;
  struct charset_info_st *charset;
  MYSQL_FIELD   *fields;
  MEM_ROOT      field_alloc;
  my_ulonglong affected_rows;
  my_ulonglong insert_id;               /* id if insert on table with NEXTNR */
  my_ulonglong extra_info;              /* Not used */
  unsigned long thread_id;              /* Id for connection in server */
  unsigned long packet_length;
  unsigned int  port;
  unsigned long client_flag,server_capabilities;
  unsigned int  protocol_version;
  unsigned int  field_count;
  unsigned int  server_status;
  unsigned int  server_language;
  unsigned int  warning_count;
  struct st_mysql_options options;
  enum mysql_status status;
  my_bool       free_me;                /* If free in mysql_close */
  my_bool       reconnect;              /* set to 1 if automatic reconnect */

  /* session-wide random string */
  char          scramble[SCRAMBLE_LENGTH+1];

 /*
   Set if this is the original connection, not a master or a slave we have
   added though mysql_rpl_probe() or mysql_set_master()/ mysql_add_slave()
 */
  my_bool rpl_pivot;
  /*
    Pointers to the master, and the next slave connections, points to
    itself if lone connection.
  */
  struct st_mysql* master, *next_slave;

  struct st_mysql* last_used_slave; /* needed for round-robin slave pick */
 /* needed for send/read/store/use result to work correctly with replication */
  struct st_mysql* last_used_con;

  LIST  *stmts;                     /* list of all statements */
  const struct st_mysql_methods *methods;
  void *thd;
  /*
    Points to boolean flag in MYSQL_RES  or MYSQL_STMT. We set this flag
    from mysql_stmt_close if close had to cancel result set of this object.
  */
  my_bool *unbuffered_fetch_owner;
  /* needed for embedded server - no net buffer to store the 'info' */
  char *info_buffer;
  void *extension;
} MYSQL;
2. MYSQL_RES
    MYSQL_RES结构代表返回行的查询结果(SELECT、SHOW、DESCRIBE等),从数据库读取数据,最后就是从MYSQL_RES中读取数据。
MYSQL_RES定义如下:
  1. typedef struct st_mysql_res {  
  2.   my_ulonglong  row_count;  
  3.   MYSQL_FIELD   *fields;  
  4.   MYSQL_DATA    *data;  
  5.   MYSQL_ROWS    *data_cursor;  
  6.   unsigned long *lengths;               /* column lengths of current row */  
  7.   MYSQL         *handle;                /* for unbuffered reads */  
  8.   const struct st_mysql_methods *methods;  
  9.   MYSQL_ROW     row;                    /* If unbuffered read */  
  10.   MYSQL_ROW     current_row;            /* buffer to current row */  
  11.   MEM_ROOT      field_alloc;  
  12.   unsigned int  field_count, current_field;  
  13.   my_bool       eof;                    /* Used by mysql_fetch_row */  
  14.   /* mysql_stmt_close() had to cancel this result */  
  15.   my_bool       unbuffered_fetch_cancelled;    
  16.   void *extension;  
  17. } MYSQL_RES;  
typedef struct st_mysql_res {
  my_ulonglong  row_count;
  MYSQL_FIELD   *fields;
  MYSQL_DATA    *data;
  MYSQL_ROWS    *data_cursor;
  unsigned long *lengths;               /* column lengths of current row */
  MYSQL         *handle;                /* for unbuffered reads */
  const struct st_mysql_methods *methods;
  MYSQL_ROW     row;                    /* If unbuffered read */
  MYSQL_ROW     current_row;            /* buffer to current row */
  MEM_ROOT      field_alloc;
  unsigned int  field_count, current_field;
  my_bool       eof;                    /* Used by mysql_fetch_row */
  /* mysql_stmt_close() had to cancel this result */
  my_bool       unbuffered_fetch_cancelled;  
  void *extension;
} MYSQL_RES;
MySQL 有如下C语言API:

函数

描述

mysql_affected_rows()

返回上次UPDATE、DELETE或INSERT查询更改/删除/插入的行数。

mysql_autocommit()

切换 autocommit模式,ON/OFF

mysql_change_user()

更改打开连接上的用户和数据库

mysql_charset_name()

返回用于连接的默认字符集的名称。

mysql_close()

关闭服务器连接。

mysql_commit()

提交事务。

mysql_connect()

连接到MySQL服务器。该函数已不再被重视,使用mysql_real_connect()取代。

mysql_create_db()

创建数据库。该函数已不再被重视,使用SQL语句CREATE DATABASE取而代之。

mysql_data_seek()

在查询结果集中查找属性行编号。

mysql_debug()

用给定的字符串执行DBUG_PUSH。

mysql_drop_db()

撤销数据库。该函数已不再被重视,使用SQL语句DROP DATABASE取而代之。

mysql_dump_debug_info()

让服务器将调试信息写入日志。

mysql_eof()

确定是否读取了结果集的最后一行。该函数已不再被重视,可以使用mysql_errno()或mysql_error()取而代之。

mysql_errno()

返回上次调用的MySQL函数的错误编号。

mysql_error()

返回上次调用的MySQL函数的错误消息。

mysql_escape_string()

为了用在SQL语句中,对特殊字符进行转义处理。

mysql_fetch_field()

返回下一个表字段的类型。

mysql_fetch_field_direct()

给定字段编号,返回表字段的类型。

mysql_fetch_fields()

返回所有字段结构的数组。

mysql_fetch_lengths()

返回当前行中所有列的长度。

mysql_fetch_row()

从结果集中获取下一行

mysql_field_seek()

将列光标置于指定的列。

mysql_field_count()

返回上次执行语句的结果列的数目。

mysql_field_tell()

返回上次mysql_fetch_field()所使用字段光标的位置。

mysql_free_result()

释放结果集使用的内存。

mysql_get_client_info()

以字符串形式返回客户端版本信息。

mysql_get_client_version()

以整数形式返回客户端版本信息。

mysql_get_host_info()

返回描述连接的字符串。

mysql_get_server_version()

以整数形式返回服务器的版本号。

mysql_get_proto_info()

返回连接所使用的协议版本。

mysql_get_server_info()

返回服务器的版本号。

mysql_info()

返回关于最近所执行查询的信息。

mysql_init()

获取或初始化MYSQL结构。

mysql_insert_id()

返回上一个查询为AUTO_INCREMENT列生成的ID。

mysql_kill()

杀死给定的线程。

mysql_library_end()

最终确定MySQL C API库。

mysql_library_init()

初始化MySQL C API库。

mysql_list_dbs()

返回与简单正则表达式匹配的数据库名称。

mysql_list_fields()

返回与简单正则表达式匹配的字段名称。

mysql_list_processes()

返回当前服务器线程的列表。

mysql_list_tables()

返回与简单正则表达式匹配的表名。

mysql_more_results()

检查是否还存在其他结果。

mysql_next_result()

在多语句执行过程中返回/初始化下一个结果。

mysql_num_fields()

返回结果集中的列数。

mysql_num_rows()

返回结果集中的行数。

mysql_options()

为mysql_connect()设置连接选项。

mysql_ping()

检查与服务器的连接是否工作,如有必要重新连接。

mysql_query()

执行指定为“以Null终结的字符串”的SQL查询。

mysql_real_connect()

连接到MySQL服务器。

mysql_real_escape_string()

考虑到连接的当前字符集,为了在SQL语句中使用,对字符串中的特殊字符进行转义处理。

mysql_real_query()

执行指定为计数字符串的SQL查询。

mysql_refresh()

刷新或复位表和高速缓冲。

mysql_reload()

通知服务器再次加载授权表。

mysql_rollback()

回滚事务。

mysql_row_seek()

使用从mysql_row_tell()返回的值,查找结果集中的行偏移。

mysql_row_tell()

返回行光标位置。

mysql_select_db()

选择数据库。

mysql_server_end()

最终确定嵌入式服务器库。

mysql_server_init()

初始化嵌入式服务器库。

mysql_set_server_option()

为连接设置选项(如多语句)。

mysql_sqlstate()

返回关于上一个错误的SQLSTATE错误代码。

mysql_shutdown()

关闭数据库服务器。

mysql_stat()

以字符串形式返回服务器状态。

mysql_store_result()

检索完整的结果集至客户端。

mysql_thread_id()

返回当前线程ID。

mysql_thread_safe()

如果客户端已编译为线程安全的,返回1。

mysql_use_result()

初始化逐行的结果集检索。

mysql_warning_count()

返回上一个SQL语句的告警数。

MySQL交互时,应用程序应使用该一般性原则:

1.    通过调用mysql_library_init(),初始化MySQL库。库可以是mysqlclient C客户端库,或mysqld嵌入式服务器库,具体情况取决于应用程序是否与“-libmysqlclient”或“-libmysqld”标志链接。

2.    通过调用mysql_init()初始化连接处理程序,并通过调用mysql_real_connect()连接到服务器。

3.    发出SQL语句并处理其结果。(在下面的讨论中,详细介绍了使用它的方法)。

4.    通过调用mysql_close(),关闭与MySQL服务器的连接。

5.    通过调用mysql_library_end(),结束MySQL库的使用。

 

        调用mysql_library_init()mysql_library_end()的目的在于,为MySQL库提供恰当的初始化和结束处理。对于与客户端库链接的应用程序,它们提供了改进的内存管理功能。如果不调用mysql_library_end(),内存块仍将保持分配状态(这不会增加应用程序使用的内存量,但某些内存泄漏检测器将抗议它)。对于与嵌入式服务器链接的应用程序,这些调用会启动并停止服务器。

        mysql_library_init()mysql_library_end()实际上是#define符号,这类符号使得它们等效于mysql_server_init()mysql_server_end(),但其名称更清楚地指明,无论应用程序使用的是mysqlclientmysqld库,启动或结束MySQL库时,应调用它们。对于早期的MySQL版本,可调用mysql_server_init()mysql_server_end()取而代之。

        如果愿意,可省略对mysql_library_init()的调用,这是因为,必要时,mysql_init()会自动调用它。

        要想连接到服务器,可调用mysql_init()来初始化连接处理程序,然后用该处理程序(以及其他信息,如主机名、用户名和密码)调用mysql_real_connect()。建立连接后,在低于5.0.3版的API中,mysql_real_connect()会将再连接标志(MYSQL结构的一部分)设置为1,或在较新的版本中,将其设置为0。对于该标志,值“1”指明,如果因连接丢失而无法执行语句,放弃之前,会尝试再次连接到服务器。从MySQL 5.0.13开始,可以在mysql_options()上使用MYSQL_OPT_RECONNECT选项,以控制再连接行为。完成连接后,调用mysql_close()中止它。

        当连接处于活动状态时,客户端或许会使用mysql_query()mysql_real_query()向服务器发出SQL查询。两者的差别在于,mysql_query()预期的查询为指定的、由Null终结的字符串,而myql_real_query()预期的是计数字符串。如果字符串包含二进制数据(其中可能包含Null字节),就必须使用mysql_real_squery()

        对于每个非SELECT查询(例如INSERTUPDATEDELETE),通过调用mysql_affected_rows(),可发现有多少行已被改变(影响)。

        对于SELECT查询,能够检索作为结果集的行。注意,某些语句因其返回行,类似与SELECT。包括SHOWDESCRIBEEXPLAIN。应按照对待SELECT语句的方式处理它们。

        客户端处理结果集的方式有两种。一种方式是,通过调用mysql_store_result(),一次性地检索整个结果集。该函数能从服务器获得查询返回的所有行,并将它们保存在客户端。第二种方式是针对客户端的,通过调用mysql_use_result(),对“按行”结果集检索进行初始化处理。该函数能初始化检索结果,但不能从服务器获得任何实际行。

        在这两种情况下,均能通过调用mysql_fetch_row()访问行。通过mysql_store_result()mysql_fetch_row()能够访问以前从服务器获得的行。通过mysql_use_result()mysql_fetch_row()能够实际地检索来自服务器的行。通过调用mysql_fetch_lengths(),能获得关于各行中数据大小的信息。

        完成结果集操作后,请调用mysql_free_result()释放结果集使用的内存。

        这两种检索机制是互补的。客户端程序应选择最能满足其要求的方法。实际上,客户端最常使用的是mysql_store_result()

        mysql_store_result()1个优点在于,由于将行全部提取到了客户端上,你不仅能连续访问行,还能使用mysql_data_seek()mysql_row_seek()在结果集中向前或向后移动,以更改结果集内当前行的位置。通过调用mysql_num_rows(),还能发现有多少行。另一方面,对于大的结果集,mysql_store_result()所需的内存可能会很大,你很可能遇到内存溢出状况。

        mysql_use_result()1个优点在于,客户端所需的用于结果集的内存较少,原因在于,一次它仅维护一行(由于分配开销较低,mysql_use_result()能更快)。它的缺点在于,你必须快速处理每一行以避免妨碍服务器,你不能随机访问结果集中的行(只能连续访问行),你不知道结果集中有多少行,直至全部检索了它们为止。不仅如此,即使在检索过程中你判定已找到所寻找的信息,也必须检索所有的行。

        通过API,客户端能够恰当地对查询作出响应(仅在必要时检索行),而无需知道查询是否是SELECT查询。可以在每次mysql_query()mysql_real_query()后,通过调用mysql_store_result()完成该操作。如果结果集调用成功,查询为SELECT,而且能够读取行。如果结果集调用失败,可调用mysql_field_count()来判断结果是否的确是所预期的。如果mysql_field_count()返回0,查询不返回数据(表明它是INSERTUPDATEDELETE等),而且不返回行。如果mysql_field_count()是非0值,查询应返回行,但没有返回行。这表明查询是失败了的SELECT。关于如何实现该操作的示例,请参见关于mysql_field_count()的介绍。

        无论是mysql_store_result()还是mysql_use_result(),均允许你获取关于构成结果集的字段的信息(字段数目,它们的名称和类型等)。通过重复调用mysql_fetch_field(),可以按顺序访问行内的字段信息,或者,通过调用mysql_fetch_field_direct(),能够在行内按字段编号访问字段信息。通过调用mysql_field_seek(),可以改变当前字段的光标位置。对字段光标的设置将影响后续的mysql_fetch_field()调用。此外,你也能通过调用mysql_fetch_fields(),一次性地获得关于字段的所有信息。

        为了检测和通报错误,MySQL提供了使用mysql_errno()mysql_error()函数访问错误信息的机制。它们能返回关于最近调用的函数的错误代码或错误消息,最近调用的函数可能成功也可能失败,这样,你就能判断错误是在何时出现的,以及错误是什么。


1.连接mysql数据库示例:
  1. #include <stdio.h>  
  2. #include <mysql.h>  
  3.   
  4. int main(int argc, const char *argv[])  
  5. {  
  6.     MYSQL   mysql;  
  7.   
  8.     if (NULL == mysql_init(&mysql)) {    //分配和初始化MYSQL对象  
  9.         printf("mysql_init(): %s\n", mysql_error(&mysql));  
  10.         return -1;  
  11.     }  
  12.   
  13.     //尝试与运行在主机上的MySQL数据库引擎建立连接  
  14.     if (NULL == mysql_real_connect(&mysql,  
  15.                 "localhost",  
  16.                 "root",  
  17.                 "shallnet",  
  18.                 "db_users",  
  19.                 0,  
  20.                 NULL,  
  21.                 0)) {  
  22.         printf("mysql_real_connect(): %s\n", mysql_error(&mysql));  
  23.         return -1;  
  24.     }  
  25.   
  26.     printf("Connected MySQL successful! \n");  
  27.   
  28.     mysql_close(&mysql);  
  29.     return 0;  
  30. }  

#include <stdio.h>
#include <mysql.h>

int main(int argc, const char *argv[])
{
    MYSQL   mysql;

    if (NULL == mysql_init(&mysql)) {    //分配和初始化MYSQL对象
        printf("mysql_init(): %s\n", mysql_error(&mysql));
        return -1;
    }

    //尝试与运行在主机上的MySQL数据库引擎建立连接
    if (NULL == mysql_real_connect(&mysql,
                "localhost",
                "root",
                "shallnet",
                "db_users",
                0,
                NULL,
                0)) {
        printf("mysql_real_connect(): %s\n", mysql_error(&mysql));
        return -1;
    }

    printf("Connected MySQL successful! \n");

    mysql_close(&mysql);
    return 0;
}
上例中使用函数说明:

        MYSQL *mysql_init(MYSQL *mysql) , 分配或初始化与mysql_real_connect()相适应的MYSQL对象。如果mysql是NULL指针,该函数将分配、初始化、并返回新对象。否则,将初始化对象,并返回对象的地址。如果mysql_init()分配了新的对象,当调用mysql_close()来关闭连接时。将释放该对象。函数返回初始化的MYSQL*句柄。如果无足够内存以分配新的对象,返回NULL。

        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()必须成功完成。

第一个参数mysql应是已有MYSQL结构的地址。

host”的值必须是主机名或IP地址。如果“host”是NULL或字符串"localhost",连接将被视为与本地主机的连接。

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

“db”是数据库名称。如果dbNULL连接会将默认的数据库设为该值。

如果“port”不是0其值将用作TCP/IP连接的端口号。注意,“host”参数决定了连接的类型。

如果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(加密协议)。该选项不应由应用程序设置,它是在客户端库内部设置的。

如果连接成功,函数返回MYSQL*连接句柄。如果连接失败,返回NULL。对于成功的连接,返回值与第1个参数的值相同。


const char *mysql_error(MYSQL *mysql);

对于由mysql指定的连接,对于失败的最近调用的API函数,mysql_error()返回包含错误消息的、由Null终结的字符串。如果该函数未失败,mysql_error()的返回值可能是以前的错误,或指明无错误的空字符串。

经验规则是,如果成功,所有向服务器请求信息的函数均会复位mysql_error()


下面为编译和执行结果输出:

  1. # make  
  2. cc -Wall -Werror -O2 -I/usr/include/mysql/   -c -o main.o main.c  
  3. Linking target_bin...  
  4. # ./target_bin   
  5. Connected MySQL successful!  
# make
cc -Wall -Werror -O2 -I/usr/include/mysql/   -c -o main.o main.c
Linking target_bin...
# ./target_bin 
Connected MySQL successful!

如果故意改错密码,编译链接之后程序输出如下信息:


  1. # ./target_bin  
  2. mysql_real_connect(): Access denied for user 'root'@'localhost' (using password: YES)  
# ./target_bin
mysql_real_connect(): Access denied for user 'root'@'localhost' (using password: YES)
2.查询数据库示例:

  1. #include <stdio.h>  
  2. #include <mysql.h>  
  3. #include <string.h>  
  4. int main(int argc, const char *argv[])  
  5. {  
  6.     MYSQL           mysql;  
  7.     MYSQL_RES       *res = NULL;  
  8.     MYSQL_ROW       row;  
  9.     char            *query_str = NULL;  
  10.     int             rc, i, fields;  
  11.     int             rows;  
  12.     if (NULL == mysql_init(&mysql)) {  
  13.         printf("mysql_init(): %s\n", mysql_error(&mysql));  
  14.         return -1;  
  15.     }  
  16.     if (NULL == mysql_real_connect(&mysql,  
  17.                 "localhost",  
  18.                 "root",  
  19.                 "shallnet",  
  20.                 "db_users",  
  21.                 0,  
  22.                 NULL,  
  23.                 0)) {  
  24.         printf("mysql_real_connect(): %s\n", mysql_error(&mysql));  
  25.         return -1;  
  26.     }  
  27.     printf("1. Connected MySQL successful! \n");  
  28.     query_str = "select * from tb_users";  
  29.     rc = mysql_real_query(&mysql, query_str, strlen(query_str));  
  30.     if (0 != rc) {  
  31.         printf("mysql_real_query(): %s\n", mysql_error(&mysql));  
  32.         return -1;  
  33.     }  
  34.     res = mysql_store_result(&mysql);  
  35.     if (NULL == res) {  
  36.          printf("mysql_restore_result(): %s\n", mysql_error(&mysql));  
  37.          return -1;  
  38.     }  
  39.     rows = mysql_num_rows(res);  
  40.     printf("The total rows is: %d\n", rows);  
  41.     fields = mysql_num_fields(res);  
  42.     printf("The total fields is: %d\n", fields);  
  43.     while ((row = mysql_fetch_row(res))) {  
  44.         for (i = 0; i < fields; i++) {  
  45.             printf("%s\t", row[i]);  
  46.         }  
  47.         printf("\n");  
  48.     }  
  49.     mysql_close(&mysql);  
  50.     return 0;  
  51. }  
#include <stdio.h>
#include <mysql.h>
#include <string.h>
int main(int argc, const char *argv[])
{
    MYSQL           mysql;
    MYSQL_RES       *res = NULL;
    MYSQL_ROW       row;
    char            *query_str = NULL;
    int             rc, i, fields;
    int             rows;
    if (NULL == mysql_init(&mysql)) {
        printf("mysql_init(): %s\n", mysql_error(&mysql));
        return -1;
    }
    if (NULL == mysql_real_connect(&mysql,
                "localhost",
                "root",
                "shallnet",
                "db_users",
                0,
                NULL,
                0)) {
        printf("mysql_real_connect(): %s\n", mysql_error(&mysql));
        return -1;
    }
    printf("1. Connected MySQL successful! \n");
    query_str = "select * from tb_users";
    rc = mysql_real_query(&mysql, query_str, strlen(query_str));
    if (0 != rc) {
        printf("mysql_real_query(): %s\n", mysql_error(&mysql));
        return -1;
    }
    res = mysql_store_result(&mysql);
    if (NULL == res) {
         printf("mysql_restore_result(): %s\n", mysql_error(&mysql));
         return -1;
    }
    rows = mysql_num_rows(res);
    printf("The total rows is: %d\n", rows);
    fields = mysql_num_fields(res);
    printf("The total fields is: %d\n", fields);
    while ((row = mysql_fetch_row(res))) {
        for (i = 0; i < fields; i++) {
            printf("%s\t", row[i]);
        }
        printf("\n");
    }
    mysql_close(&mysql);
    return 0;
}
int mysql_real_query(MYSQL *mysql, const char *query, unsigned long length)

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

        对于包含二进制数据的查询,必须使用mysql_real_query()而不是mysql_query(),这是因为,二进制数据可能会包含\0’字符。此外,mysql_real_query()mysql_query()快,这是因为它不会在查询字符串上调用strlen()如果查询成功,函数返回0。如果出现错误,函数返回非0值。


MYSQL_RES *mysql_store_result(MYSQL *mysql)

        对于成功检索了数据的每个查询(SELECTSHOWDESCRIBEEXPLAINCHECK TABLE),必须调用mysql_store_result()mysql_use_result()

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

如果希望了解查询是否应返回结果集,可使用mysql_field_count()进行检查。mysql_store_result()将查询的全部结果读取到客户端,分配1MYSQL_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()

返回具有多个结果的MYSQL_RES结果集合。如果出现错误,返回NULL。

my_ulonglong mysql_num_rows(MYSQL_RES *result)

        函数返回结果集中的行数,mysql_num_rows()的使用取决于是否采用了mysql_store_result()mysql_use_result()来返回结果集。如果使用了mysql_store_result(),可以立刻调用mysql_num_rows()。如果使用了mysql_use_result()mysql_num_rows()不返回正确的值,直至检索了结果集中的所有行为止,函数结果集中的行数。

unsigned int mysql_num_fields(MYSQL_RES *result)

要想传递MYSQL*参量取而代之,请使用无符号整数mysql_field_count(MYSQL *mysql)

        函数返回结果集中的列数。注意,你可以从指向结果集的指针或指向连接句柄的指针获得行数。如果mysql_store_result()mysql_use_result()返回NULL,应使用连接句柄(因而没有结果集指针)。在该情况下,可调用mysql_field_count()来判断mysql_store_result()是否生成了非空结果。这样,客户端程序就能采取恰当的行动,而不需要知道查询是否是SELECT语句(或类似SELECT的语句)。

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

void mysql_free_result(MYSQL_RES *result)

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

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


编译链接执行结果如下:


  1. # make  
  2. cc -Wall -Werror -O2 -I/usr/include/mysql/   -c -o main.o main.c  
  3. Linking target_bin...  
  4. # ./target_bin   
  5. 1. Connected MySQL successful!   
  6. The total rows is: 13  
  7. The total fields is: 3  
  8. 10000   Allen   1981-01-01  
  9. 10001   Ben     1982-04-02  
  10. 10002   Curry   1985-08-12  
  11. 10003   Davis   1978-07-12  
  12. 10004   Ellis   1979-09-02  
  13. 10005   Faried  1984-02-05  
  14. 10007   Hamilton        1988-07-07  
  15. 10008   Johnson 1986-06-07  
  16. 10009   Jackson 1989-08-17  
  17. 10010   James   1984-12-30  
  18. 10011   Gay     1987-02-03  
  19. 10012   Kaman   1981-04-04  
  20. 10006   Wade    1982-03-04  
# make
cc -Wall -Werror -O2 -I/usr/include/mysql/   -c -o main.o main.c
Linking target_bin...
# ./target_bin 
1. Connected MySQL successful! 
The total rows is: 13
The total fields is: 3
10000   Allen   1981-01-01
10001   Ben     1982-04-02
10002   Curry   1985-08-12
10003   Davis   1978-07-12
10004   Ellis   1979-09-02
10005   Faried  1984-02-05
10007   Hamilton        1988-07-07
10008   Johnson 1986-06-07
10009   Jackson 1989-08-17
10010   James   1984-12-30
10011   Gay     1987-02-03
10012   Kaman   1981-04-04
10006   Wade    1982-03-04

插入删除示例:
  1. #include <stdio.h>  
  2. #include <mysql.h>  
  3. #include <string.h>  
  4. int main(int argc, const char *argv[])  
  5. {  
  6.     MYSQL           mysql;  
  7.     MYSQL_RES       *res = NULL;  
  8.     MYSQL_ROW       row;  
  9.     char            *query_str = NULL;  
  10.     int             rc, i, fields;  
  11.     int             rows;  
  12.     if (NULL == mysql_init(&mysql)) {  
  13.         printf("mysql_init(): %s\n", mysql_error(&mysql));  
  14.         return -1;  
  15.     }  
  16.     if (NULL == mysql_real_connect(&mysql,  
  17.                 "localhost",  
  18.                 "root",  
  19.                 "shallnet",  
  20.                 "db_users",  
  21.                 0,  
  22.                 NULL,  
  23.                 0)) {  
  24.         printf("mysql_real_connect(): %s\n", mysql_error(&mysql));  
  25.         return -1;  
  26.     }  
  27.     printf("1. Connected MySQL successful! \n");  
  28. //执行插入请求  
  29.     query_str = "insert into tb_users values (12345, 'justtest', '2015-5-5')";  
  30.     rc = mysql_real_query(&mysql, query_str, strlen(query_str));  
  31.     if (0 != rc) {  
  32.         printf("mysql_real_query(): %s\n", mysql_error(&mysql));  
  33.         return -1;  
  34.     }  
  35. //执行删除请求  
  36.     query_str = "delete from tb_users where userid=10006";  
  37.     rc = mysql_real_query(&mysql, query_str, strlen(query_str));  
  38.     if (0 != rc) {  
  39.         printf("mysql_real_query(): %s\n", mysql_error(&mysql));  
  40.         return -1;  
  41.     }  
  42. //然后查询插入删除之后的数据  
  43.     query_str = "select * from tb_users";  
  44.     rc = mysql_real_query(&mysql, query_str, strlen(query_str));  
  45.     if (0 != rc) {  
  46.         printf("mysql_real_query(): %s\n", mysql_error(&mysql));  
  47.         return -1;  
  48.     }  
  49.     res = mysql_store_result(&mysql);  
  50.     if (NULL == res) {  
  51.          printf("mysql_restore_result(): %s\n", mysql_error(&mysql));  
  52.          return -1;  
  53.     }  
  54.     rows = mysql_num_rows(res);  
  55.     printf("The total rows is: %d\n", rows);  
  56.     fields = mysql_num_fields(res);  
  57.     printf("The total fields is: %d\n", fields);  
  58.     while ((row = mysql_fetch_row(res))) {  
  59.         for (i = 0; i < fields; i++) {  
  60.             printf("%s\t", row[i]);  
  61.         }  
  62.         printf("\n");  
  63.     }  
  64.     mysql_free_result(res);  
  65.     mysql_close(&mysql);  
  66.     return 0;  
  67. }  
#include <stdio.h>
#include <mysql.h>
#include <string.h>
int main(int argc, const char *argv[])
{
    MYSQL           mysql;
    MYSQL_RES       *res = NULL;
    MYSQL_ROW       row;
    char            *query_str = NULL;
    int             rc, i, fields;
    int             rows;
    if (NULL == mysql_init(&mysql)) {
        printf("mysql_init(): %s\n", mysql_error(&mysql));
        return -1;
    }
    if (NULL == mysql_real_connect(&mysql,
                "localhost",
                "root",
                "shallnet",
                "db_users",
                0,
                NULL,
                0)) {
        printf("mysql_real_connect(): %s\n", mysql_error(&mysql));
        return -1;
    }
    printf("1. Connected MySQL successful! \n");
//执行插入请求
    query_str = "insert into tb_users values (12345, 'justtest', '2015-5-5')";
    rc = mysql_real_query(&mysql, query_str, strlen(query_str));
    if (0 != rc) {
        printf("mysql_real_query(): %s\n", mysql_error(&mysql));
        return -1;
    }
//执行删除请求
    query_str = "delete from tb_users where userid=10006";
    rc = mysql_real_query(&mysql, query_str, strlen(query_str));
    if (0 != rc) {
        printf("mysql_real_query(): %s\n", mysql_error(&mysql));
        return -1;
    }
//然后查询插入删除之后的数据
    query_str = "select * from tb_users";
    rc = mysql_real_query(&mysql, query_str, strlen(query_str));
    if (0 != rc) {
        printf("mysql_real_query(): %s\n", mysql_error(&mysql));
        return -1;
    }
    res = mysql_store_result(&mysql);
    if (NULL == res) {
         printf("mysql_restore_result(): %s\n", mysql_error(&mysql));
         return -1;
    }
    rows = mysql_num_rows(res);
    printf("The total rows is: %d\n", rows);
    fields = mysql_num_fields(res);
    printf("The total fields is: %d\n", fields);
    while ((row = mysql_fetch_row(res))) {
        for (i = 0; i < fields; i++) {
            printf("%s\t", row[i]);
        }
        printf("\n");
    }
    mysql_free_result(res);
    mysql_close(&mysql);
    return 0;
}

编译链接执行结果如下:

  1. # make   
  2. cc -Wall -Werror -O2 -I/usr/include/mysql/   -c -o main.o main.c  
  3. Linking target_bin...  
  4. # ./target_bin  
  5. 1. Connected MySQL successful!  
  6. The total rows is: 13  
  7. The total fields is: 3  
  8. 10000   Allen   1981-01-01  
  9. 10001   Ben     1982-04-02  
  10. 10002   Curry   1985-08-12  
  11. 10003   Davis   1978-07-12  
  12. 10004   Ellis   1979-09-02  
  13. 10005   Faried  1984-02-05  
  14. 10007   Hamilton        1988-07-07  
  15. 10008   Johnson 1986-06-07  
  16. 10009   Jackson 1989-08-17  
  17. 10010   James   1984-12-30  
  18. 10011   Gay     1987-02-03  
  19. 10012   Kaman   1981-04-04  
  20. 12345   justtest        2015-05-05  
# make 
cc -Wall -Werror -O2 -I/usr/include/mysql/   -c -o main.o main.c
Linking target_bin...
# ./target_bin
1. Connected MySQL successful!
The total rows is: 13
The total fields is: 3
10000   Allen   1981-01-01
10001   Ben     1982-04-02
10002   Curry   1985-08-12
10003   Davis   1978-07-12
10004   Ellis   1979-09-02
10005   Faried  1984-02-05
10007   Hamilton        1988-07-07
10008   Johnson 1986-06-07
10009   Jackson 1989-08-17
10010   James   1984-12-30
10011   Gay     1987-02-03
10012   Kaman   1981-04-04
12345   justtest        2015-05-05

本节源码下载:
至此本系列就讲完了,内容不多,我们的目的是快速学会mysql的编程开发,并未深入讲解数据库的基本原理以及mysql的各方面操作。在这几节内容里面只涉及常用操作,其他细节问题可以在以后开发中遇到了再深入了解,在最后一节进行了编程开发,这使得读者只需要在很短的时间进入到开发中来,不被细枝末节所扰,这也是笔者的目的。最后欢迎大家拍砖!
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/It_BeeCoder/article/details/71304189

智能推荐

电力系统潮流计算c加加语言指南,第三章简单电力系统的潮流计算汇总_工程师李涛的博客-程序员宝宝

1、第一章 简单电力系统的分析和计算一、 基本要求掌握电力线路中的电压降落和功率损耗的计算、变压器中的电压降落和功率损耗的计算;掌握辐射形网络的潮流分布计算;掌握简单环形网络的潮流分布计算;了解电力网络的简化。二、 重点内容1、 电力线路中的电压降落和功率损耗图3-1中,设线路末端电压为、末端功率为,则(1)计算电力线路中的功率损耗 线路末端导纳支路的功率损耗: (3-1)则阻抗支路末端的功率为:...

2020年天梯赛真题——L2-3 完全二叉树的层序遍历_白鹿贞松的博客-程序员宝宝

一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是完美二叉树。对于深度为 D 的,有 N 个结点的二叉树,若其结点对应于相同深度完美二叉树的层序遍历的前 N 个结点,这样的树就是完全二叉树。给定一棵完全二叉树的后序遍历,请你给出这棵树的层序遍历结果。输入格式:输入在第一行中给出正整数 N(≤30),即树中结点个数。第二行给出后序遍历序列,为 N 个不超过 100 的正整数。同一行中所有数字都以空格分隔。输出格式:在一行中输出该树的层序遍历序列。所有数字都以 1 个空格分隔,行首尾不得有

黑马程序员--网络编程_weixin_30780221的博客-程序员宝宝

端口号的范围:0-65535,其中0-1024系统已经占用,例如:WEB端口:80;mysql端口:3306;tomcat:8080;在网络通信里,  1、传输层协议:    TCP协议,类似于打电话(下载)      1.建立连接,创建连接两端的通道(通过三次握手)      2.适合传输大数据      3.可靠地      4.由于需要建立连接,效率低...

淘宝在数据处理领域的项目及开源产品介绍_weixin_30739595的博客-程序员宝宝

淘宝在数据存储和处理领域在国内互联网公司中一直保持比较靠前的位置,而且由于电子商务领域独特的应用场景,淘宝在数据实时性和大规模计算及挖掘方面一直在国内保持着领先,因此积累了很多的实践的经验和产品。TimeTunnel基于Hbase打造的消息中间件,具有高可靠、消息顺序、事务等传统特性,还能按时间维度反复订阅最近历史的任意数据高性能的broker,单节点达2万TPS,实际支持上千长链...

android怎么自动获取权限不弹窗,android-su-without-dialog_weixin_39752352的博客-程序员宝宝

举例:runasroot的用法,首先到download runasroot下载,需要经过赋予权限,root用户组所有,可执行,拷贝到/system/bin,再切换到普通用户,然后就万事大吉,可以在普通shell里面执行需要root权限才能执行的命令$adb push runasroot /data/local/tmp/$adb [email protected]:/data/local/tmp ...

6-3 Add Two Polynomials(20 分)_四月~的博客-程序员宝宝

6-3 Add Two Polynomials(20 分)Write a function to add two polynomials. Do not destroy the input. Use a linked list implementation with a dummy head node. Note: The zero polynomial is represented by an ...

随便推点

Eigen与matlab的比较_汤姆与贝塔的博客-程序员宝宝_eigen matlab

Eigen和Matlab比较// 参考 - http://eigen.tuxfamily.org/dox/AsciiQuickReference.txt// 一个关于Eigen的快速参考// Matlab和Eigen的对应用法// Main author: Keir Mierle// 注释:张学志#include Eigen/Dense>Matrixdouble, 3, 3>

集群_weixin_33753003的博客-程序员宝宝

何为集群?百度上面的解释就已经够了:集群是一组相互独立的、通过高速网络互联的计算机,它们构成了一个组,并以单一系统的模式加以管理。一个客户与集群相互作用时,集群像是一个独立的服务器。集群配置是用于提高可用性和可缩放性。集群的作用:1.提高性能 2.降低成本 3.提高可扩展性 4.增强可靠性这4点很好理解,所以从这4点作用来看我们可以把集群分为三类:1.超级计算集群 2.负载均衡集群 3.高可用...

网站上传图片提示错误怎么办_qq_1547479934的博客-程序员宝宝_图片请求上传接口出现异常

网站上传图片出现错误,或错误提示原因1:99%是图片太大,可以换个图片,或者将图片压缩一下试试原因2:图片格式问题, 上传的格式不在允许范围。原因3:国外服务器, 网络卡顿,连接超时导致的上传错误,不排除存在其他问题的可能性,不同问题处理方法不同。...

Python输出时出现乱码“�밴���������. . . ”的解决方案_xgc0102的博客-程序员宝宝_python 命令行输出乱码

输出时出现“�밴���������. . . ”乱码解决方案左上角File下点击Setting...点击File Encodings修改Global Encoding为GBK重新运行程序不再出现乱码

jquery插件整理篇(一)导航类jq插件,菜单jq插件_国安小昊23的博客-程序员宝宝_jq插件

(1)Horizontal accordion: jQuery基于jQuery开发,非常简单的水平方向折叠控件。(2)jQuery-Horizontal Accordion具有XBOX360 blade界面风格的水平方向Accordion。(3)jQuery plugin: Accordion用于创建 折叠菜单的jQuery插件。(4

创建动态视图_weixin_30649641的博客-程序员宝宝

http://www.cbf107.com/CBF107Item.aspx?ID=79c98c3e-aea2-46f9-baa7-1ccd067e2a81SQLServer2005 Pivot 转置使用动态列(应用到视图)SQLServer2005 Pivot转置使用动态列(应用到视图)最近项目中用到Pivot对表进行转置,遇到一些问题,主要是Pivot转置的时候没有办法...

推荐文章

热门文章

相关标签