原文地址:http://www.2cto.com/database/201506/407827.htmlphp
在实际应用中,咱们不可能在命令行登陆进数据库进行数据的查询、插入等操做,用户通常是使用一个界面良好的应用程序软件来对数据进行管理。为了方便应用程序的开发,MySQL提供了多种编程语言(C、perl、php等)的编程接口,供开发者使用。 对于C语言来讲,MySQL提供了C语言客户机库,它容许从任何C程序的内部访问MySQL数据库,客户机实现API,API定义了客户机如何创建和执行与服务器的通讯。使用C语言开发MySQL项目具备更好的安全性和性能,C语言API是与MySQL一块儿提供的,包含在mysqlclient库文件中,用于链接和执行数据库查询。 首先看一下MySQL为C语言操做定义的数据类型。 1. MYSQL,MYSQL结构表明一个数据库链接句柄,包含有关服务器的链接状态的信息,几乎全部函数都是用到它。其定 义以下:html
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定义以下:
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 |
描述正则表达式 |
mysql_affected_rows()sql |
返回上次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(),但其名称更清楚地指明,不管应用程序使用的是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、DESCRIBE和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_field(),能够按顺序访问行内的字段信息,或者,经过调用mysql_fetch_field_direct(),可以在行内按字段编号访问字段信息。经过调用mysql_field_seek(),能够改变当前字段的光标位置。对字段光标的设置将影响后续的mysql_fetch_field()调用。此外,你也能经过调用mysql_fetch_fields(),一次性地得到关于字段的全部信息。
为了检测和通报错误,MySQL提供了使用mysql_errno()和mysql_error()函数访问错误信息的机制。它们能返回关于最近调用的函数的错误代码或错误消息,最近调用的函数可能成功也可能失败,这样,你就能判断错误是在什么时候出现的,以及错误是什么。
#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”是数据库名称。若是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。对于成功的链接,返回值与第1个参数的值相同。
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!
#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”。正常状况下,字符串必须包含1条SQL语句,并且不该为语句添加终结分号(‘;’)或“\g”。若是容许多语句执行,字符串可包含由分号隔开的多条语句。
对于包含二进制数据的查询,必须使用mysql_real_query()而不是mysql_query(),这是由于,二进制数据可能会包含‘\0’字符。此外,mysql_real_query()比mysql_query()快,这是由于它不会在查询字符串上调用strlen()。若是查询成功,函数返回0。若是出现错误,函数返回非0值。
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()进行检查。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_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()释放结果集使用的内存。
释放完成后,不要尝试访问结果集。
编译连接执行结果以下:
# 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 <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; }编译连接执行结果以下:
# 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