使用C语言开发MySQL项目具有更好的安全性和性能

作者: www.9159.com  发布:2019-10-01

 

有关Mysql的mysql_store_result函数重回NULL的意况以及别的注意事项,mysqlstoreresult

打响调用mysql_query()后,mysql_store_result()可以回到NULL。出现本场合时,证明出现了下述条件之一:

·         出现了malloc()故障(举个例子,如若结果集过大)。

·         不恐怕读取数据(在延续上冒出了错误)。

·         查询未回到数据(比方,它是INSERT、UPDATE或DELETE)。

经过调用mysql_field_count(),始终能检查语句是还是不是应生成非空结果。要是mysql_field_count()再次来到0,结果为空,並且上叁个询问是未再次回到值的言辞(比方INSERT或DELETE)。要是mysql_field_count()再次回到非0值,语句应生成非空结果。关于那上头的身体力行,请参见mysql_field_count()函数介绍:

回来功效在连接上的近日询问的列数。该函数的正规使用是在mysql_store_result()重返NULL(由此未有结果集指针)时。在这种意况下,可调用mysql_field_count()来判定mysql_store_result()是或不是应生成非空结果。那样,顾客端就会应用适当的动作,而无需清楚查询是不是是SELECT(或周边SELECT的)语句。在这里给出的示范中,演示了成功它的法子。重返表示结果聚集列数的无符号整数。

另一种可选的诀要是,用mysql_errno(&mysql)替换mysql_field_count(&mysql)调用。在该意况下,无论语句是不是是SELECT,你将平素从mysql_store_result()查找错误,并非从mysql_field_count()的值进行推理。

通过调用mysql_error()或mysql_errno(),可测量试验是或不是出现了不当。

 

注意:

对于成功调用mysql_query()实行select语句的询问,固然查询的数量不设有(即rowcount=0),result也不为NULL。result为NULL的情景只是检查实验上多少个询问是不是是有重回值的说话。

 

范例:

MYSQL_RES *result; unsigned int num_fields; unsigned int num_rows; if (mysql_query(&mysql,query_string)) { // error } else // query succeeded, process any data returned by it { result = mysql_store_result(&mysql); if (result) // there are rows { num_fields = mysql_num_fields(result); // retrieve rows, then call mysql_free_result(result) } else // mysql_store_result() returned nothing; should it have? { if(mysql_field_count(&mysql) == 0) { // query does not return data // (it was not a SELECT) num_rows = mysql_affected_rows(&mysql); } else // mysql_store_result() should have returned data { fprintf(stderr, "Error: %sn", mysql_error(&mysql)); } } }

 转载请表明地址:

成功调用mysql_query()后, mysql_store_result() 能够回来NULL。现身该...

解决linux上MySQL编制程序(六):C语言编写MySQL程序(结)

在实际应用中,大家不容许在命令行登陆进数据库进行数据的询问、插入等操作,客户日常是运用一个分界面能够的应用程序软件来对数据开展田间管理。为了有援救应用程序的支付,MySQL提供了二种编制程序语言(C、perl、php等)的编程接口,供开荒者使用。 对于C语言来讲,MySQL提供了C语言顾客机库,它同意从任何C程序的内部访问MySQL数据库,客商机落成API,API定义了顾客机怎样营造和实施与服务器的通讯。使用C语言开辟MySQL项目具备越来越好的安全性和品质,C语言API是与MySQL一同提供的,包涵在mysqlclient库文件中,用于连接和举办数据库查询。 首先看一下MySQL为C语言操作定义的数据类型。 1. MYSQL,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;
  1. MYSQL_RES MYSQL_RES结构意味着再次回到行的询问结果(SELECT、SHOW、DESCENVISIONIBE等),从数据库读取数据,最终便是从MYSQL_RES中读取数据。 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()连接到服务器。

  1. 发生SQL语句并拍卖其结果。(在下边包车型大巴研究中,详细介绍了运用它的方法)。

  2. 经过调用mysql_close(),关闭与MySQL服务器的三回九转。

  3. 透过调用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(),但其名目更通晓地指明,无论应用程序使用的是mysqlclient或mysqld库,运行或甘休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查询(举个例子INSERT、UPDATE、DELETE),通过调用mysql_affected_rows(),可窥见有微微行已被更动(影响)。

对于SELECT查询,能够找出作为结果集的行。注意,有些语句因其再次回到行,类似与SELECT。包蕴SHOW、DESC讴歌MDXIBE和EXPLAIN。应服从对待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,查询不回去数据(评释它是INSERT、UPDATE、DELETE等),并且不再次来到行。要是mysql_field_count()是非0值,查询应重临行,但尚未回来行。那注明查询是战败了的SELECT。关于什么促成该操作的身体力行,请参见关于mysql_field_count()的介绍。

无论是mysql_store_result()还是mysql_use_result(),均同意你拿走有关构成结果集的字段的新闻(字段数目,它们的称呼和体系等)。通过重复调用mysql_fetch_田野(),能够按顺序访谈行内的字段新闻,或然,通过调用mysql_fetch_field_direct(),能够在行内按字段编号访谈字段音信。通过调用mysql_field_seek(),能够改动如今字段的光标地方。对字段光标的装置将影响连续的mysql_fetch_田野先生()调用。另外,你也能通过调用mysql_fetch_田野s(),壹遍性地获取有关字段的兼具音讯。

为了检查评定和文告错误,MySQL提供了利用mysql_errno()和mysql_error()函数访谈错误消息的编写制定。它们能回到关于方今调用的函数的错误代码或错误新闻,近期调用的函数大概得逞也恐怕停业,那样,你就会判断错误是在曾几何时出现的,以及错误是如何。

1.连接mysql数据库示例:

#include 
#include 

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

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

    //尝试与运行在主机上的MySQL数据库引擎建立连接
    if (NULL == mysql_real_connect(&mysql,
                "localhost",
                "root",
                "shallnet",
                "db_users",
                0,
                NULL,
                0)) {
        printf("mysql_real_connect(): %sn", 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()必需成功实现。

www.9159.com , 

第二个参数mysql应是已有MYSQL结构的地点。

 

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

 

“passwd”参数包罗客商的密码。如果“passwd”是NULL,仅会对该客户的(具有1个空密码字段的)客商表中的条约实行相称检查。那样,数据库管理员就能按一定的诀窍设置MySQL权限系统,依据客户是还是不是有所内定的密码,客户将赢得分化的权位。

“db”是数据库名称。纵然db为NULL,连接会将私下认可的数据库设为该值。

 

一经“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。对于成功的接连,再次回到值与首个参数的值同样。

 

const char *mysql_error(MYSQL *mysql);

对于由mysql内定的连天,对于停业的前段时间调用的API函数,mysql_error()再次来到包涵错误音讯的、由Null终结的字符串。借使该函数未失利,mysql_error()的再次来到值恐怕是先前的荒谬,或指明无不当的空字符串。

经历法则是,假设成功,全部向服务器乞求消息的函数均会重新设置mysql_error()。

上面为编写翻译和实践结果输出:

 

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

 

要是有意改错密码,编写翻译链接之后前后相继输出如下音信:

 

# ./target_bin
mysql_real_connect(): Access denied for user 'root'@'localhost' (using password: YES)

2.查询数据库示例:

 

#include 
#include 
#include 
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(): %sn", mysql_error(&mysql));
        return -1;
    }
    if (NULL == mysql_real_connect(&mysql,
                "localhost",
                "root",
                "shallnet",
                "db_users",
                0,
                NULL,
                0)) {
        printf("mysql_real_connect(): %sn", 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(): %sn", mysql_error(&mysql));
        return -1;
    }
    res = mysql_store_result(&mysql);
    if (NULL == res) {
         printf("mysql_restore_result(): %sn", mysql_error(&mysql));
         return -1;
    }
    rows = mysql_num_rows(res);
    printf("The total rows is: %dn", rows);
    fields = mysql_num_fields(res);
    printf("The total fields is: %dn", fields);
    while ((row = mysql_fetch_row(res))) {
        for (i = 0; i < fields; i++) {
            printf("%st", row[i]);
        }
        printf("n");
    }
    mysql_close(&mysql);
    return 0;
}

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

进行由“query”指向的SQL查询,它应是字符串长度字节“long”。符合规律情况下,字符串必得带有1条SQL语句,并且不应当为语句加多终结分号(‘;’)或“g”。假若允好些个语句推行,字符串可含蓄由支行隔离的多条语句。

对于蕴含二进制数据的查询,必需利用mysql_real_query()而不是mysql_query(),那是因为,二进制数据或许会蕴藏‘’字符。此外,mysql_real_query()比mysql_query()快,那是因为它不会在查询字符串上调用strlen()。假使查询成功,函数重返0。要是出现错误,函数重返非0值。

MYSQL_RES *mysql_store_result(MYSQL *mysql)

对此成功检索了数据的种种查询(SELECT、SHOW、DESC翼虎IBE、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()举办反省。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()。

重回具备八个结实的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_田野(field)s(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()释放结果集应用的内部存储器。

刑释完结后,不要品味访问结果集。

编写翻译链接推行结果如下:

 

# 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

 

插入删除示例:

#include 
#include 
#include 
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(): %sn", mysql_error(&mysql));
        return -1;
    }
    if (NULL == mysql_real_connect(&mysql,
                "localhost",
                "root",
                "shallnet",
                "db_users",
                0,
                NULL,
                0)) {
        printf("mysql_real_connect(): %sn", 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(): %sn", 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(): %sn", 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(): %sn", mysql_error(&mysql));
        return -1;
    }
    res = mysql_store_result(&mysql);
    if (NULL == res) {
         printf("mysql_restore_result(): %sn", mysql_error(&mysql));
         return -1;
    }
    rows = mysql_num_rows(res);
    printf("The total rows is: %dn", rows);
    fields = mysql_num_fields(res);
    printf("The total fields is: %dn", fields);
    while ((row = mysql_fetch_row(res))) {
        for (i = 0; i < fields; i++) {
            printf("%st", row[i]);
        }
        printf("n");
    }
    mysql_free_result(res);
    mysql_close(&mysql);
    return 0;
}

编写翻译链接试行结果如下:

 

# 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

 

在实质上运用中,大家不容许在命令行登入进数据库进行数据的询问、插入等操作,用...

·         查询未归来数据(举个例子,它是INSERT、UPDATE或DELETE)。

 转载请注明地址:

归来效用在接连上的近年来询问的列数。该函数的常规使用是在mysql_store_result()再次来到NULL(因此未有结果集指针)时。在这种情形下,可调用mysql_field_count()来判定mysql_store_result()是或不是应生成非空结果。那样,客户端就会应用适度的动作,而无需精晓查询是不是是SELECT(或相近SELECT的)语句。在此处给出的示范中,演示了成功它的形式。重回表示结果聚焦列数的无符号整数。

范例:

对于成功调用mysql_query()实行select语句的询问,就算查询的数目海市蜃楼(即rowcount=0),result也不为NULL。result为NULL的情事只是检查实验上三个询问是还是不是是有再次回到值的话语。

另一种可选的主意是,用mysql_errno(&mysql)替换mysql_field_count(&mysql)调用。在该情形下,无论语句是不是是SELECT,你将一直从mysql_store_result()查找错误,并非从mysql_field_count()的值实行推理。

通过调用mysql_field_count(),始终能检查语句是不是应生成非空结果。假如mysql_field_count()再次回到0,结果为空,何况上二个询问是未重临值的语句(例如INSERT或DELETE)。借使mysql_field_count()再次回到非0值,语句应生成非空结果。关于那方面包车型大巴亲自去做,请参见mysql_field_count()函数介绍:

成功调用mysql_query()后,mysql_store_result()可见回到NULL。出现该情形时,申明现身了下述条件之一:

 

透过调用mysql_error()或mysql_errno(),可测验是还是不是出现了不当。

 1     MYSQL_RES *result;
 2     unsigned int num_fields;
 3     unsigned int num_rows;
 4     if (mysql_query(&mysql, query_string))
 5     {
 6         // error
 7     }
 8     else // query succeeded, process any data returned by it
 9     {
10         result = mysql_store_result(&mysql);
11         if (result) // there are rows
12         {
13             num_fields = mysql_num_fields(result);
14             // retrieve rows, then call mysql_free_result(result)
15         }
16         else // mysql_store_result() returned nothing; should it have?
17         {
18             if (mysql_field_count(&mysql) == 0)
19             {
20                 // query does not return data
21                 // (it was not a SELECT)
22                 num_rows = mysql_affected_rows(&mysql);
23             }
24             else // mysql_store_result() should have returned data
25             {
26                 fprintf(stderr, "Error: %sn", mysql_error(&mysql));
27             }
28         }
29     }

注意:

 

·         现身了malloc()故障(举个例子,若是结果集过大)。

·         无法读取数据(在连年上冒出了错误)。

本文由9159.com发布于www.9159.com,转载请注明出处:使用C语言开发MySQL项目具有更好的安全性和性能

关键词: