### 第25章:API和库
[本章介绍了MySQL可使用的API,从哪里获得它们,以及如何使用它们。]() 详细介绍C API,这是因为它是由MySQL团队开发的,而且它也是大多数其他API的基础。 本章还介绍了libmysqld库(嵌入式服务器),以及对应用程序开发人员有用的一些程序。
### 25.1. libmysqld,嵌入式MySQL服务器库
[25.1.1. 嵌入式MySQL服务器库概述](#)[ 25.1.2. 使用libmysqld编译程序``](#)[ 25.1.3. 使用嵌入式MySQL服务器时的限制](#)[25.1.4. 与嵌入式服务器一起使用的选项](#)[ 25.1.5. 嵌入式服务器中尚需完成的事项(TODO)](#)[ 25.1.6. 嵌入式服务器示例](#)[ 25.1.7. 嵌入式服务器的许可](#)
### 25.1.1. 嵌入式MySQL服务器库概述
使用嵌入式MySQL服务器库,能够在客户端应用程序中使用具备全部特性的MySQL服务器。 主要优点在于,增加了速度,并使得嵌入式应用程序的管理更简单。
嵌入式服务器库是以MySQL的客户端/服务器版本为基础的,采用C/C++语言编写。 其结果是嵌入式服务器也是用C/C++语言编写的。 在其他语言中,嵌入式服务器不可用。
API与嵌入式MySQL版本和客户端/服务器版本等效。 要想更改旧的线程式应用程序以使用嵌入式库,正常情况下,仅需添加对下述函数的调用即可。
<table border="1" cellpadding="0" id="table1"><tr><td> <p><b>函数</b></p></td> <td> <p><b>何时调用</b></p></td> </tr><tr><td> <p> <span>mysql_server_init()</span></p></td> <td> <p>应在调用任何其他MySQL函数之前调用,最好是在<span>main()函数中调用。</span></p></td> </tr><tr><td> <p> <span>mysql_server_end()</span></p></td> <td> <p>应在程序退出前调用。</p></td> </tr><tr><td> <p> <span>mysql_thread_init()</span></p></td> <td> <p>应在你所创建的、用于访问MySQL的每个线程中调用。</p></td> </tr><tr><td> <p> <span>mysql_thread_end()</span></p></td> <td> <p>应在调用<span>pthread_exit()之前调用。</span></p></td> </tr></table>
随后,必须将你的代码与libmysqld.a链接起来,而不是libmysqlclient.a。
在libmysqlclient.a中还包含mysql_server__xxx_()函数,使用这类函数,通过将应用程序链接到恰当的库,即可在嵌入式版本和客户端/服务器版本之间切换。 请参见[25.2.12.1节,“mysql_server_init()”](# "25.2.12.1. mysql_server_init()")。
嵌入式服务器和独立服务器之间的一项差别在于,对于嵌入式服务器,默认情况下,连接鉴定是禁止的。 对于嵌入式服务器,要想使用鉴定功能,可在激活“**configure**”以配置MySQL分发版时使用“--with-embedded-privilege-control”选项。
### 25.1.2. 使用libmysqld编译程序``
要想获得libmysqld库,应使用“--with-embedded-server”选项配置MySQL。 请参见[2.8.2节,“典型配置选项****”](# "2.8.2. Typical configure Options")。
将你的程序与libmysqld链接时,还必须包含系统的pthread库以及MySQL服务器使用的一些库。 执行“**mysql_config --libmysqld-libs**”,可获得库的完整列表。
对于线程程序的编译和链接,必须使用正确的标志,即使你未在代码中直接调用任何线程函数也同样。
要想编译C程序以包含必要文件,并将MySQL服务器库嵌入到程序的编译版本中,可使用GNU C编译器(gcc)。 编译器需要知道各种文件的位置,并需了解如何编译程序的指令。 在下面的示例中,介绍了如何从命令行编译程序的方法:
gcc mysql_test.c -o mysql_test -lz \
`/usr/local/mysql/bin/mysql_config --include --libmysqld-libs`
在gcc命令后紧跟着未编译C程序文件的名称。 接下来,给定的“-o”选项指明,它后面的文件名是编译器将输出文件的名称,即编译后的程序。 在下一行的代码中,通知编译器获取包含文件和库的位置,以及在其上进行编译的系统的其他设置。 由于“**mysql_config**”存在的问题,在此添加了“-lz”选项(压缩)。 “**mysql_config**”部分包含在backticks中,而不是单引号内。
### 25.1.3. 使用嵌入式MySQL服务器时的限制
嵌入式服务器存在下述限制:
· 不支持ISAM表。 (这样做的主要目的是为了使库更小)。
· 没有自定义函数(UDF)。
· 没有对核心转储的堆栈跟踪。
· 没有内部RAID支持。 (由于大多数当前操作系统均支持大文件,通常情况下不需要它)。
· 不能将其设置为“主”或“从”(无复制)。
· 在内存较低的系统上,可能无法使用很大的结果集。
· 不能使用套接字或TCP/IP从外部进程连接到嵌入式服务器。 但是,你可以连接到中间应用程序,随后,该中间应用程序可代表远程客户端或外部进程连接到嵌入式服务器。
通过编辑“mysql_embed.h”包含文件并重新编译MySQL,可更改某些限制。
### 25.1.4. 与嵌入式服务器一起使用的选项
对于任何能够与**mysqld**服务器端口监督程序一起给定的选项,也可以与嵌入式服务器库一起使用。在数组中,可将服务器选项作为参量指定给用于初始化服务器的mysql_server_init()。也能在诸如my.cnf的选项文件中给定它们。要想为C程序指定选项文件,请使用“--defaults-file”选项作为函数mysql_server_init()的第2个参量的元素之一。关于mysql_server_init()函数的更多信息,请参见[25.2.12.1节,“mysql_server_init()”](# "25.2.12.1. mysql_server_init()")。
使用选项文件,能够简化客户端/服务器应用程序和嵌入了MySQL的应用程序之间的切换。将常用选项置于[server]组。它们可被两种MySQL版本读取。客户端/服务器选项应被放在[mysqld]部分。将嵌入式MySQL服务器库的选项放在[embedded]部分。将与应用程序相关的选项放在标记为[ApplicationName_SERVER]的部分。请参见[4.3.2节,“使用选项文件”](# "4.3.2. Using Option Files")。
### 25.1.5. 嵌入式服务器中尚需完成的事项(TODO)
· 我们将提供一些选项以省去MySQL的某些部分,从而使库变得更小。
· 仍有很多速度优化工作需要完成。
· 错误将被写入stderr。我们将增加1个选项为它们指定文件名。
· 使用嵌入式版本时,需要更改InnoDB,使之不再冗长。如果你的数据库不含InnoDB表,要想抑制相关消息,可为组[libmysqd_server]下的选项文件增加“--skip-innodb”选项,或在用**mysql_server_init()**初始化服务器时添加该选项。
### 25.1.6. 嵌入式服务器示例
在Linux或FreeBSD系统上,无需更改就能使用下面这两个示例程序。对于其他操作系统,需要进行小的修改,主要是文件路径。设计这两个示例的目的在于,为你提供足够的细节信息,以便理解问题,它们是实际应用程序的必要组成部份。第1个示例十分直观。第2个示例采用了一些错误检查功能,略为复杂。在第1个示例的后面,给出了用于编译程序的命令行条目。在第2个示例的后面,给出了GNUmake文件,该文件可用于编译。
**示例:1**
test1_libmysqld.c
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "mysql.h"
MYSQL *mysql;
MYSQL_RES *results;
MYSQL_ROW record;
static char *server_options[] = { "mysql_test", "--defaults-file=my.cnf" };
int num_elements = sizeof(server_options)/ sizeof(char *);
static char *server_groups[] = { "libmysqld_server", "libmysqld_client" };
int main(void)
{
mysql_server_init(num_elements, server_options, server_groups);
mysql = mysql_init(NULL);
mysql_options(mysql, MYSQL_READ_DEFAULT_GROUP, "libmysqld_client");
mysql_options(mysql, MYSQL_OPT_USE_EMBEDDED_CONNECTION, NULL);
mysql_real_connect(mysql, NULL,NULL,NULL, "database1", 0,NULL,0);
mysql_query(mysql, "SELECT column1, column2 FROM table1");
results = mysql_store_result(mysql);
while((record = mysql_fetch_row(results))) {
printf("%s - %s \n", record[0], record[1]);
}
mysql_free_result(results);
mysql_close(mysql);
mysql_server_end();
return 0;
}
下面给出了编译上述程序的命令行命令:
gcc test1_libmysqld.c -o test1_libmysqld -lz \
`/usr/local/mysql/bin/mysql_config --include --libmysqld-libs`
**示例:2**
要想检验该示例,创建一个与MySQL源目录同级的test2_libmysqld目录。将test2_libmysqld.c源文件和GNUmakefile保存到该目录,并在test2_libmysqld目录下运行GNU make。
test2_libmysqld.c
/*
* A simple example client, using the embedded MySQL server library
*/
#include <mysql.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
MYSQL *db_connect(const char *dbname);
void db_disconnect(MYSQL *db);
void db_do_query(MYSQL *db, const char *query);
const char *server_groups[] = {
"test2_libmysqld_SERVER", "embedded", "server", NULL
};
int
main(int argc, char **argv)
{
MYSQL *one, *two;
/* mysql_server_init() must be called before any other mysql
* functions.
*
* You can use mysql_server_init(0, NULL, NULL), and it
* initializes the server using groups = {
* "server", "embedded", NULL
* }.
*
* In your $HOME/.my.cnf file, you probably want to put:
[test2_libmysqld_SERVER]
language = /path/to/source/of/mysql/sql/share/english
* You could, of course, modify argc and argv before passing
* them to this function. Or you could create new ones in any
* way you like. But all of the arguments in argv (except for
* argv[0], which is the program name) should be valid options
* for the MySQL server.
*
* If you link this client against the normal mysqlclient
* library, this function is just a stub that does nothing.
*/
mysql_server_init(argc, argv, (char **)server_groups);
one = db_connect("test");
two = db_connect(NULL);
db_do_query(one, "SHOW TABLE STATUS");
db_do_query(two, "SHOW DATABASES");
mysql_close(two);
mysql_close(one);
/* This must be called after all other mysql functions */
mysql_server_end();
exit(EXIT_SUCCESS);
}
static void
die(MYSQL *db, char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
(void)putc('\n', stderr);
if (db)
db_disconnect(db);
exit(EXIT_FAILURE);
}
MYSQL *
db_connect(const char *dbname)
{
MYSQL *db = mysql_init(NULL);
if (!db)
die(db, "mysql_init failed: no memory");
/*
* Notice that the client and server use separate group names.
* This is critical, because the server does not accept the
* client's options, and vice versa.
*/
mysql_options(db, MYSQL_READ_DEFAULT_GROUP, "test2_libmysqld_CLIENT");
if (!mysql_real_connect(db, NULL, NULL, NULL, dbname, 0, NULL, 0))
die(db, "mysql_real_connect failed: %s", mysql_error(db));
return db;
}
void
db_disconnect(MYSQL *db)
{
mysql_close(db);
}
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, end_row;
int num_fields;
if (!(res = mysql_store_result(db)))
goto err;
num_fields = mysql_num_fields(res);
while ((row = mysql_fetch_row(res)))
{
(void)fputs(">> ", stdout);
for (end_row = row + num_fields; row < end_row; ++row)
(void)printf("%s\t", row ? (char*)*row : "NULL");
(void)fputc('\n', stdout);
}
(void)fputc('\n', stdout);
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);
}
GNUmakefile
# This assumes the MySQL software is installed in /usr/local/mysql
inc := /usr/local/mysql/include/mysql
lib := /usr/local/mysql/lib
# If you have not installed the MySQL software yet, try this instead
#inc := $(HOME)/mysql-5.1/include
#lib := $(HOME)/mysql-5.1/libmysqld
CC := gcc
CPPFLAGS := -I$(inc) -D_THREAD_SAFE -D_REENTRANT
CFLAGS := -g -W -Wall
LDFLAGS := -static
# You can change -lmysqld to -lmysqlclient to use the
# client/server library
LDLIBS = -L$(lib) -lmysqld -lz -lm -lcrypt
ifneq (,$(shell grep FreeBSD /COPYRIGHT 2>/dev/null))
# FreeBSD
LDFLAGS += -pthread
else
# Assume Linux
LDLIBS += -lpthread
endif
# This works for simple one-file test programs
sources := $(wildcard *.c)
objects := $(patsubst %c,%o,$(sources))
targets := $(basename $(sources))
all: $(targets)
clean:
rm -f $(targets) $(objects) *.core
### 25.1.7. 嵌入式服务器的许可
我们鼓励所有人在GPL或兼容许可的旗帜下通过发布代码来推广免费软件。对于有能力完成该类事项的人员,也可以选择从MySQL AB购买MySQL的商用许可。详情请参见[http://www.mysql.com/company/legal/licensing/](http://www.mysql.com/company/legal/licensing/)。
### 25.2. MySQL C API
[ 25.2.1. C API数据类型](#)[ 25.2.2. C API函数概述](#)[ 25.2.3. C API函数描述](#)[ 25.2.4. C API预处理语句](#)[ 25.2.5. C API预处理语句的数据类型](#)[ 25.2.6. C API预处理语句函数概述](#)[ 25.2.7. C API预处理语句函数描述](#)[ 25.2.8. C API预处理语句方面的问题](#)[ 25.2.9. 多查询执行的C API处理](#)[ 25.2.10. 日期和时间值的C API处理](#)[ 25.2.11. C API线程函数介绍](#)[ 25.2.12. C API嵌入式服务器函数介绍](#)[ 25.2.13. 使用C API时的常见问题](#)[ 25.2.14. 创建客户端程序](#)[ 25.2.15. 如何生成线程式客户端](#)
C API代码是与MySQL一起提供的。它包含在mysqlclient库中,并允许C程序访问数据库。
MySQL源码分发版的很多客户端是用C语言编写的。如果你正在寻找能演示如何使用C API的示例,可参看这些客户端程序。你可以在MySQL源码分发版的客户端目录下找到它们。
大多数其他客户端API(除了Connector/J和Connector/NET)采用mysqlclient库来与MySQL服务器进行通信。这意味着(例如),你可以利用很多相同环境变量(与其他客户端程序使用的环境变量相同)带来的好处,这是因为它们是从库中引用的。关于这些变量的详细清单,请参见[第8章:](#)[_客户端和实用工具程序_](# "Chapter 8. Client and Utility Programs")。
客户端具有最大的通信缓冲区大小。初始分配的缓冲区大小(16KB)将自动增加到最大(最大为16MB)。由于缓冲区大小将按需增加,简单地增加默认的最大限制,从其本身来说不会增加资源使用。该大小检查主要是检查错误查询和通信信息包。
通信缓冲区必须足够大,足以包含1条SQL语句(用于客户端-服务器通信)以及1行返回的数据(用于服务器-客户端通信)。每个线程的通信缓冲区将动态增加,以处理直至最大限制的任何查询或行。例如,如果BLOB值包含高达16MB的数据,那么通信缓冲区的大小限制至少为16MB(在服务器和客户端)。客户端的默认最大值为16MB,但服务器的默认最大值为1MB。也可以在启动服务器时,通过更改max_allowed_packet参数的值增加它。请参见[7.5.2节,“调节服务器参数”](# "7.5.2. Tuning Server Parameters")。
每次查询后,MySQL服务器会将通信缓冲区的大小降至net_buffer_length字节。对于客户端,不会降低与连接相关缓冲区大小,直至连接关闭为止,此时,客户端内存将被收回。
关于使用线程的编程方法,请参见[25.2.15节,“如何生成线程式客户端”](# "25.2.15. How to Make a Threaded Client")。关于在相同程序创建包含“服务器”和“客户端”的独立应用程序的更多信息(不与外部MySQL服务器通信),请参见[25.1节,“libmysqld,嵌入式MySQL服务器库”](# "25.1. libmysqld, the Embedded MySQL Server Library")。
### 25.2.1. C API数据类型
-
MYSQL
该结构代表1个数据库连接的句柄。几乎所有的MySQL函数均使用它。不应尝试拷贝MYSQL结构。不保证这类拷贝结果会有用。
-
MYSQL_RES
该结构代表返回行的查询结果(SELECT, SHOW, DESCRIBE, EXPLAIN)。在本节的剩余部分,将查询返回的信息称为“结果集”。
-
MYSQL_ROW
这是1行数据的“类型安全”表示。它目前是按照计数字节字符串的数组实施的。(如果字段值可能包含二进制数据,不能将其当作由Null终结的字符串对待,这是因为这类值可能会包含Null字节)。行是通过调用mysql_fetch_row()获得的。
-
MYSQL_FIELD
该结构包含关于字段的信息,如字段名、类型和大小。这里详细介绍了其成员。通过重复调用mysql_fetch_field(),可为每个字段获得MYSQL_FIELD结构。字段值不是该结构的组成部份,它们包含在MYSQL_ROW结构中。
-
MYSQL_FIELD_OFFSET
这是MySQL字段列表偏移量的“类型安全”表示(由mysql_field_seek()使用)。偏移量是行内的字段编号,从0开始。
-
my_ulonglong
用于行数以及mysql_affected_rows()、mysql_num_rows()和mysql_insert_id()的类型。该类型提供的范围为0~1.84e19。
在某些系统上,不能打印类型my_ulonglong的值。要想打印这类值,请将其转换为无符号长整数类型并使用%lu打印格式,例如:
printf ("Number of rows: %lu\n", (unsigned long) mysql_num_rows(result));
下面列出了MYSQL_FIELD结构包含的成员:
· char * name
字段名称,由Null终结的字符串。如果用AS子句为该字段指定了别名,名称的值也是别名。
· char * org_name
段名称,由Null终结的字符串。忽略别名。
· char * table
包含该字段的表的名称,如果该字段不是计算出的字段的话。对于计算出的字段,表值为空的字符串。如果用AS子句为该表指定了别名,表的值也是别名。
· char * org_table
表的名称,由Null终结的字符串。忽略别名。
· char * db
字段源自的数据的名称,由Null终结的字符串。如果该字段是计算出的字段,db为空的字符串。
· char * catalog
catalog名称。该值总是"def"。
· char * def
该字段的默认值,由Null终结的字符串。仅当使用mysql_list_fields()时才设置它。
· unsigned long length
字段的宽度,如表定义中所指定的那样。
· unsigned long max_length
用于结果集的字段的最大宽度(对于实际位于结果集中的行,最长字段值的长度)。如果使用mysql_store_result()或mysql_list_fields(),它将包含字段的最大长度。如果使用mysql_use_result(),该变量的值为0。
· unsigned int name_length
名称的长度。
· unsigned int org_name_length
org_name的长度。
· unsigned int table_length
表的长度。
· unsigned int org_table_length
org_table的长度。
· unsigned int db_length
db的长度。
· unsigned int catalog_length
catalog的长度。
· unsigned int def_length
def的长度。
· unsigned int flags
用于字段的不同“位标志”。标志的值可以有0个或多个下述位集合:
<table border="1" cellpadding="0" id="table2"><tr><td> <p><strong><span> 标志值</span></strong></p></td> <td> <p><strong><span> 标志描述</span></strong></p></td> </tr><tr><td> <p> <span>NOT_NULL_FLAG</span></p></td> <td> <p>字段不能为<span>NULL</span></p></td> </tr><tr><td> <p> <span>PRI_KEY_FLAG</span></p></td> <td> <p>字段是主键的组成部分</p></td> </tr><tr><td> <p> <span>UNIQUE_KEY_FLAG</span></p></td> <td> <p>字段是唯一键的组成部分</p></td> </tr><tr><td> <p> <span>MULTIPLE_KEY_FLAG</span></p></td> <td> <p>字段是非唯一键的组成部分</p></td> </tr><tr><td> <p> <span>UNSIGNED_FLAG</span></p></td> <td> <p>字段具有<span>UNSIGNED</span>属性</p></td> </tr><tr><td> <p> <span>ZEROFILL_FLAG</span></p></td> <td> <p>字段具有<span>ZEROFILL</span>属性</p></td> </tr><tr><td> <p> <span>BINARY_FLAG</span></p></td> <td> <p>字段具有<span>BINARY</span>属性</p></td> </tr><tr><td> <p> <span>AUTO_INCREMENT_FLAG</span></p></td> <td> <p>字段具有<span>AUTO_INCREMENT</span>属性</p></td> </tr><tr><td> <p> <span>ENUM_FLAG</span></p></td> <td> <p>字段是<span>ENUM</span>(不再重视)</p></td> </tr><tr><td> <p> <span>SET_FLAG</span></p></td> <td> <p>字段是 <span>SET</span>(不再重视)</p></td> </tr><tr><td> <p> <span>BLOB_FLAG</span></p></td> <td> <p>字段是<span>BLOB</span>或<span>TEXT</span>(不再重视)</p></td> </tr><tr><td> <p> <span>TIMESTAMP_FLAG</span></p></td> <td> <p>字段是<span>TIMESTAMP</span>(不再重视)</p></td> </tr></table>
不再重视BLOB_FLAG、ENUM_FLAG、SET_FLAG和TIMESTAMP_FLAG标志,原因在于,它们指出了字段的类型,而不是类型的属性。更可取的方式是使用MYSQL_TYPE_BLOB、MYSQL_TYPE_ENUM、MYSQL_TYPE_SET或MYSQL_TYPE_TIMESTAMP测试field->type。
在下面的示例中,介绍了标志值的典型用法:
if (field->flags & NOT_NULL_FLAG)
printf("Field can't be null\n");
可以使用下述方面的宏来定义标志值的布尔状态:
<table border="1" cellpadding="0" id="table3"><tr><td> <p><strong><span> 标志状态</span></strong></p></td> <td> <p><strong><span> 描述</span></strong></p></td> </tr><tr><td> <p> <span>IS_NOT_NULL(flags)</span></p></td> <td> <p>如果该字段定义为<span><span>NOT NULL</span>,为<span>“</span>真<span>”</span>。</span></p></td> </tr><tr><td> <p> <span>IS_PRI_KEY(flags)</span></p></td> <td> <p>如果该字段是主键<span>,为<span>“</span>真<span>”</span>。</span></p></td> </tr><tr><td> <p> <span>IS_BLOB(flags)</span></p></td> <td> <p>如果该字段是<span>BLOB</span>或<span>TEXT</span><span>,为<span>“</span>真<span>”</span>(不再重视</span>,用测试<span>field->type</span>取而代之)。</p></td> </tr></table>
· unsigned int decimals
用于数值字段的十进制数数目。
· unsigned int charset_nr
用于字段的字符集编号。
· enum enum_field_types type
字段的类型。类型值可以是下标所列的MYSQL_TYPE_符号之一:
<table border="1" cellpadding="0" id="table4"><tr><td> <p><strong><span> 类型值</span></strong></p></td> <td> <p><strong><span> 类型描述</span></strong></p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_TINY</span></p></td> <td> <p> <span>TINYINT</span>字段</p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_SHORT</span></p></td> <td> <p> <span>SMALLINT</span>字段</p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_LONG</span></p></td> <td> <p> <span>INTEGER</span>字段</p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_INT24</span></p></td> <td> <p> <span>MEDIUMINT</span>字段</p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_LONGLONG</span></p></td> <td> <p> <span>BIGINT</span>字段</p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_DECIMAL</span></p></td> <td> <p> <span>DECIMAL</span>或<span>NUMERIC</span>字段</p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_NEWDECIMAL</span></p></td> <td> <p>精度数学<span>DECIMAL</span>或<span>NUMERIC</span></p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_FLOAT</span></p></td> <td> <p> <span>FLOAT</span>字段</p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_DOUBLE</span></p></td> <td> <p> <span>DOUBLE</span>或<span>REAL</span>字段</p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_BIT</span></p></td> <td> <p> <span>BIT</span>字段</p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_TIMESTAMP</span></p></td> <td> <p> <span>TIMESTAMP</span>字段</p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_DATE</span></p></td> <td> <p> <span>DATE</span>字段</p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_TIME</span></p></td> <td> <p> <span>TIME</span>字段</p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_DATETIME</span></p></td> <td> <p> <span>DATETIME</span>字段</p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_YEAR</span></p></td> <td> <p> <span>YEAR</span>字段</p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_STRING</span></p></td> <td> <p> <span>CHAR</span>字段</p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_VAR_STRING</span></p></td> <td> <p> <span>VARCHAR</span>字段</p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_BLOB</span></p></td> <td> <p> <span>BLOB</span>或<span>TEXT</span>字段(使用<span><span>max_length</span>来确定最大长度)</span></p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_SET</span></p></td> <td> <p> <span>SET</span>字段</p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_ENUM</span></p></td> <td> <p> <span>ENUM</span>字段</p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_GEOMETRY</span></p></td> <td> <p><span>Spatial</span>字段</p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_NULL</span></p></td> <td> <p> <span>NULL</span><span>-type</span>字段</p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_CHAR</span></p></td> <td> <p>不再重视,用<span>MYSQL_TYPE_TINY</span>取代</p></td> </tr></table>
可以使用IS_NUM()宏来测试字段是否具有数值类型。将类型值传递给IS_NUM(),如果字段为数值类型,会将其评估为“真”:
if (IS_NUM(field->type))
printf("Field is numeric\n");
### 25.2.2. C API函数概述
这里归纳了C API可使用的函数,并在下一节详细介绍了它们。请参见[25.2.3节,“C API函数描述”](# "25.2.3. C API Function Descriptions")。
<table border="1" cellpadding="0" id="table5"><tr><td> <p><strong><span> 函数</span></strong></p></td> <td> <p><strong><span> 描述</span></strong></p></td> </tr><tr><td> <p><strong> <span> mysql_affected_rows()</span></strong></p></td> <td> <p>返回上次<span>UPDATE</span>、<span>DELETE</span>或<span><span>INSERT</span>查询更改/删除/插入的行数。</span></p></td> </tr><tr><td> <p><strong> <span>mysql_autocommit()</span></strong></p></td> <td> <p>切换<span> autocommit</span>模式,<span>ON/OFF</span></p></td> </tr><tr><td> <p><strong> <span>mysql_change_user()</span></strong></p></td> <td> <p>更改打开连接上的用户和数据库。</p></td> </tr><tr><td> <p><strong> <span> mysql_charset_name()</span></strong></p></td> <td> <p>返回用于连接的默认字符集的名称。</p></td> </tr><tr><td> <p><strong> <span>mysql_close()</span></strong></p></td> <td> <p>关闭服务器连接。</p></td> </tr><tr><td> <p><strong> <span>mysql_commit()</span></strong></p></td> <td> <p>提交事务。</p></td> </tr><tr><td> <p><strong> <span>mysql_connect()</span></strong></p></td> <td> <p>连接到<span>MySQL</span>服务器。该函数已不再被重视,使用<span>mysql_real_connect()</span>取代。</p></td> </tr><tr><td> <p><strong> <span>mysql_create_db()</span></strong></p></td> <td> <p>创建数据库。该函数已不再被重视,使用<span>SQL</span>语句<span>CREATE DATABASE</span>取而代之。</p></td> </tr><tr><td> <p><strong> <span>mysql_data_seek()</span></strong></p></td> <td> <p>在查询结果集中查找属性行编号。</p></td> </tr><tr><td> <p><strong> <span>mysql_debug()</span></strong></p></td> <td> <p>用给定的字符串执行<span>DBUG_PUSH</span>。</p></td> </tr><tr><td> <p><strong> <span>mysql_drop_db()</span></strong></p></td> <td> <p>撤销数据库。该函数已不再被重视,使用<span>SQL</span>语句<span>DROP DATABASE</span>取而代之。</p></td> </tr><tr><td> <p><strong> <span> mysql_dump_debug_info()</span></strong></p></td> <td> <p>让服务器将调试信息写入日志。</p></td> </tr><tr><td> <p><strong> <span>mysql_eof()</span></strong></p></td> <td> <p>确定是否读取了结果集的最后一行。该函数已不再被重视,可以使用<span>mysql_errno()</span>或<span>mysql_error()</span>取而代之。</p></td> </tr><tr><td> <p><strong> <span>mysql_errno()</span></strong></p></td> <td> <p>返回上次调用的<span>MySQL</span>函数的错误编号。</p></td> </tr><tr><td> <p><strong> <span>mysql_error()</span></strong></p></td> <td> <p>返回上次调用的<span>MySQL</span>函数的错误消息。</p></td> </tr><tr><td> <p><strong> <span> mysql_escape_string()</span></strong></p></td> <td> <p>为了用在<span>SQL</span>语句中,对特殊字符进行转义处理。</p></td> </tr><tr><td> <p><strong> <span>mysql_fetch_field()</span></strong></p></td> <td> <p>返回下一个表字段的类型。</p></td> </tr><tr><td> <p><strong> <span> mysql_fetch_field_direct()</span></strong></p></td> <td> <p>给定字段编号,返回表字段的类型。</p></td> </tr><tr><td> <p><strong> <span> mysql_fetch_fields()</span></strong></p></td> <td> <p>返回所有字段结构的数组。</p></td> </tr><tr><td> <p><strong> <span> mysql_fetch_lengths()</span></strong></p></td> <td> <p>返回当前行中所有列的长度。</p></td> </tr><tr><td> <p><strong> <span>mysql_fetch_row()</span></strong></p></td> <td> <p>从结果集中获取下一行</p></td> </tr><tr><td> <p><strong> <span>mysql_field_seek()</span></strong></p></td> <td> <p>将列光标置于指定的列。</p></td> </tr><tr><td> <p><strong> <span>mysql_field_count()</span></strong></p></td> <td> <p>返回上次执行语句的结果列的数目。</p></td> </tr><tr><td> <p><strong> <span>mysql_field_tell()</span></strong></p></td> <td> <p>返回上次<span><span>mysql_fetch_field()</span>所使用字段光标的位置。</span></p></td> </tr><tr><td> <p><strong> <span>mysql_free_result()</span></strong></p></td> <td> <p>释放结果集使用的内存。</p></td> </tr><tr><td> <p><strong> <span> mysql_get_client_info()</span></strong></p></td> <td> <p>以字符串形式返回客户端版本信息。</p></td> </tr><tr><td> <p><strong> <span> mysql_get_client_version()</span></strong></p></td> <td> <p>以整数形式返回客户端版本信息。</p></td> </tr><tr><td> <p><strong> <span> mysql_get_host_info()</span></strong></p></td> <td> <p>返回描述连接的字符串。</p></td> </tr><tr><td> <p><strong> <span> mysql_get_server_version()</span></strong></p></td> <td> <p>以整数形式返回服务器的版本号。</p></td> </tr><tr><td> <p><strong> <span> mysql_get_proto_info()</span></strong></p></td> <td> <p>返回连接所使用的协议版本。</p></td> </tr><tr><td> <p><strong> <span> mysql_get_server_info()</span></strong></p></td> <td> <p>返回服务器的版本号。</p></td> </tr><tr><td> <p><strong> <span>mysql_info()</span></strong></p></td> <td> <p>返回关于最近所执行查询的信息。</p></td> </tr><tr><td> <p><strong> <span>mysql_init()</span></strong></p></td> <td> <p>获取或初始化<span>MYSQL</span>结构。</p></td> </tr><tr><td> <p><strong> <span>mysql_insert_id()</span></strong></p></td> <td> <p>返回上一个查询为<span><span>AUTO_INCREMENT</span>列生成的</span><span>ID</span>。</p></td> </tr><tr><td> <p><strong> <span>mysql_kill()</span></strong></p></td> <td> <p>杀死给定的线程。</p></td> </tr><tr><td> <p><strong> <span>mysql_library_end()</span></strong></p></td> <td> <p>最终确定<span>MySQL C API</span>库。</p></td> </tr><tr><td> <p><strong> <span> mysql_library_init()</span></strong></p></td> <td> <p>初始化<span>MySQL C API</span>库。</p></td> </tr><tr><td> <p><strong> <span>mysql_list_dbs()</span></strong></p></td> <td> <p>返回与简单正则表达式匹配的数据库名称。</p></td> </tr><tr><td> <p><strong> <span>mysql_list_fields()</span></strong></p></td> <td> <p>返回与简单正则表达式匹配的字段名称。</p></td> </tr><tr><td> <p><strong> <span> mysql_list_processes()</span></strong></p></td> <td> <p>返回当前服务器线程的列表。</p></td> </tr><tr><td> <p><strong> <span>mysql_list_tables()</span></strong></p></td> <td> <p>返回与简单正则表达式匹配的表名。</p></td> </tr><tr><td> <p><strong> <span> mysql_more_results()</span></strong></p></td> <td> <p>检查是否还存在其他结果。</p></td> </tr><tr><td> <p><strong> <span>mysql_next_result()</span></strong></p></td> <td> <p>在多语句执行过程中返回<span>/</span>初始化下一个结果。</p></td> </tr><tr><td> <p><strong> <span>mysql_num_fields()</span></strong></p></td> <td> <p>返回结果集中的列数。</p></td> </tr><tr><td> <p><strong> <span>mysql_num_rows()</span></strong></p></td> <td> <p>返回结果集中的行数。</p></td> </tr><tr><td> <p><strong> <span>mysql_options()</span></strong></p></td> <td> <p>为<span><span>mysql_connect()</span>设置连接选项。</span></p></td> </tr><tr><td> <p><strong> <span>mysql_ping()</span></strong></p></td> <td> <p>检查与服务器的连接是否工作,如有必要重新连接。</p></td> </tr><tr><td> <p><strong> <span>mysql_query()</span></strong></p></td> <td> <p>执行指定为“以<span>Null</span>终结的字符串”的<span>SQL</span>查询。</p></td> </tr><tr><td> <p><strong> <span> mysql_real_connect()</span></strong></p></td> <td> <p>连接到<span>MySQL</span>服务器。</p></td> </tr><tr><td> <p><strong> <span> mysql_real_escape_string()</span></strong></p></td> <td> <p>考虑到连接的当前字符集,为了在<span>SQL</span>语句中使用,对字符串中的特殊字符进行转义处理。</p></td> </tr><tr><td> <p><strong> <span>mysql_real_query()</span></strong></p></td> <td> <p>执行指定为计数字符串的<span>SQL</span>查询。</p></td> </tr><tr><td> <p><strong> <span>mysql_refresh()</span></strong></p></td> <td> <p>刷新或复位表和高速缓冲。</p></td> </tr><tr><td> <p><strong> <span>mysql_reload()</span></strong></p></td> <td> <p>通知服务器再次加载授权表。</p></td> </tr><tr><td> <p><strong> <span>mysql_rollback()</span></strong></p></td> <td> <p>回滚事务。</p></td> </tr><tr><td> <p><strong> <span>mysql_row_seek()</span></strong></p></td> <td> <p>使用从<span><span>mysql_row_tell()</span>返回的值,查找结果集中的行偏移。</span></p></td> </tr><tr><td> <p><strong> <span>mysql_row_tell()</span></strong></p></td> <td> <p>返回行光标位置。</p></td> </tr><tr><td> <p><strong> <span>mysql_select_db()</span></strong></p></td> <td> <p>选择数据库。</p></td> </tr><tr><td> <p><strong> <span>mysql_server_end()</span></strong></p></td> <td> <p>最终确定嵌入式服务器库。</p></td> </tr><tr><td> <p><strong> <span>mysql_server_init()</span></strong></p></td> <td> <p>初始化嵌入式服务器库。</p></td> </tr><tr><td> <p><strong> <span> mysql_set_server_option()</span></strong></p></td> <td> <p>为连接设置选项(如多语句)。</p></td> </tr><tr><td> <p><strong> <span>mysql_sqlstate()</span></strong></p></td> <td> <p>返回关于上一个错误的<span>SQLSTATE</span>错误代码。</p></td> </tr><tr><td> <p><strong> <span>mysql_shutdown()</span></strong></p></td> <td> <p>关闭数据库服务器。</p></td> </tr><tr><td> <p><strong> <span>mysql_stat()</span></strong></p></td> <td> <p>以字符串形式返回服务器状态。</p></td> </tr><tr><td> <p><strong> <span> mysql_store_result()</span></strong></p></td> <td> <p>检索完整的结果集至客户端。</p></td> </tr><tr><td> <p><strong> <span>mysql_thread_id()</span></strong></p></td> <td> <p>返回当前线程<span>ID</span>。</p></td> </tr><tr><td> <p><strong> <span>mysql_thread_safe()</span></strong></p></td> <td> <p>如果客户端已编译为线程安全的,返回<span>1</span>。</p></td> </tr><tr><td> <p><strong> <span>mysql_use_result()</span></strong></p></td> <td> <p>初始化逐行的结果集检索。</p></td> </tr><tr><td> <p><strong> <span> mysql_warning_count()</span></strong></p></td> <td> <p>返回上一个<span>SQL</span>语句的告警数。</p></td> </tr></table>
与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终结的字符串,而mysql_real_query()预期的是计数字符串。如果字符串包含二进制数据(其中可能包含Null字节),就必须使用mysql_real_query()。
对于每个非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()函数访问错误信息的机制。它们能返回关于最近调用的函数的错误代码或错误消息,最近调用的函数可能成功也可能失败,这样,你就能判断错误是在何时出现的,以及错误是什么。
### 25.2.3. C API函数描述
[25.2.3.1. mysql_affected_rows()](#)[25.2.3.2. mysql_autocommit()](#)[25.2.3.3. mysql_change_user()](#)[25.2.3.4. mysql_character_set_name()](#)[25.2.3.5. mysql_close()](#)[25.2.3.6. mysql_commit()](#)[25.2.3.7. mysql_connect()](#)[25.2.3.8. mysql_create_db()](#)[25.2.3.9. mysql_data_seek()](#)[25.2.3.10. mysql_debug()](#)[25.2.3.11. mysql_drop_db()](#)[25.2.3.12. mysql_dump_debug_info()](#)[25.2.3.13. mysql_eof()](#)[25.2.3.14. mysql_errno()](#)[25.2.3.15. mysql_error()](#)[25.2.3.16. mysql_escape_string()](#)[25.2.3.17. mysql_fetch_field()](#)[25.2.3.18. mysql_fetch_field_direct()](#)[25.2.3.19. mysql_fetch_fields()](#)[25.2.3.20. mysql_fetch_lengths()](#)[25.2.3.21. mysql_fetch_row()](#)[25.2.3.22. mysql_field_count()](#)[25.2.3.23. mysql_field_seek()](#)[25.2.3.24. mysql_field_tell()](#)[25.2.3.25. mysql_free_result()](#)[25.2.3.26. mysql_get_character_set_info()](#)[25.2.3.27. mysql_get_client_info()](#)[25.2.3.28. mysql_get_client_version()](#)[25.2.3.29. mysql_get_host_info()](#)[25.2.3.30. mysql_get_proto_info()](#)[25.2.3.31. mysql_get_server_info()](#)[25.2.3.32. mysql_get_server_version()](#)[25.2.3.33. mysql_hex_string()](#)[25.2.3.34. mysql_info()](#)[25.2.3.35. mysql_init()](#)[25.2.3.36. mysql_insert_id()](#)[25.2.3.37. mysql_kill()](#)[25.2.3.38. mysql_library_end()](#)[25.2.3.39. mysql_library_init()](#)[25.2.3.40. mysql_list_dbs()](#)[25.2.3.41. mysql_list_fields()](#)[25.2.3.42. mysql_list_processes()](#)[25.2.3.43. mysql_list_tables()](#)[25.2.3.44. mysql_more_results()](#)[25.2.3.45. mysql_next_result()](#)[25.2.3.46. mysql_num_fields()](#)[25.2.3.47. mysql_num_rows()](#)[25.2.3.48. mysql_options()](#)[25.2.3.49. mysql_ping()](#)[25.2.3.50. mysql_query()](#)[25.2.3.51. mysql_real_connect()](#)[25.2.3.52. mysql_real_escape_string()](#)[25.2.3.53. mysql_real_query()](#)[25.2.3.54. mysql_refresh()](#)[25.2.3.55. mysql_reload()](#)[25.2.3.56. mysql_rollback()](#)[25.2.3.57. mysql_row_seek()](#)[25.2.3.58. mysql_row_tell()](#)[25.2.3.59. mysql_select_db()](#)[25.2.3.60. mysql_set_character_set()](#)[25.2.3.61. mysql_set_server_option()](#)[25.2.3.62. mysql_shutdown()](#)[25.2.3.63. mysql_sqlstate()](#)[25.2.3.64. mysql_ssl_set()](#)[25.2.3.65. mysql_stat()](#)[25.2.3.66. mysql_store_result()](#)[25.2.3.67. mysql_thread_id()](#)[25.2.3.68. mysql_use_result()](#)[25.2.3.69. mysql_warning_count()](#)
在本节所作的介绍中,按照C编程语言,为NULL的参数或返回值表示NULL,而不是MySQL Null值。
返回值的函数通常会返回指针或整数。除非作了其他规定,返回指针的函数将返回非Null值,以指明成功,或返回NULL值以指明出错。返回整数的函数将返回0以指明成功,或返回非0值以指明出错。注意,非0值仅表明这点。除非在函数描述中作了其他说明,不要对非0值进行测试:
if (result) /* correct */
... error ...
if (result < 0) /* incorrect */
... error ...
if (result == -1) /* incorrect */
... error ...
当函数返回错误时,在函数描述的“错误”部分将列出可能的错误类型。通过调用mysql_errno()可发现出现的错误是什么。通过调用mysql_error(),可获得错误的字符串表示。
#### 25.2.3.1. mysql_affected_rows()
my_ulonglong mysql_affected_rows(MYSQL *mysql)
**描述**
返回上次UPDATE更改的行数,上次DELETE删除的行数,或上次INSERT语句插入的行数。对于UPDATE、DELETE或INSERT语句,可在mysql_query()后立刻调用。对于SELECT语句,mysql_affected_rows()的工作方式与mysql_num_rows()类似。
**返回值**
大于0的整数表明受影响或检索的行数。“0”表示UPDATE语句未更新记录,在查询中没有与WHERE匹配的行,或未执行查询。“-1”表示查询返回错误,或者,对于SELECT查询,在调用mysql_store_result()之前调用了mysql_affected_rows()。由于mysql_affected_rows()返回无符号值,通过比较返回值和“(my_ulonglong)-1”或等效的“(my_ulonglong)~0”,检查是否为“-1”。
**错误**
无。
**示例:**
mysql_query(&mysql,"UPDATE products SET cost=cost*1.25 WHERE group=10");
printf("%ld products updated",(long) mysql_affected_rows(&mysql));
如果在连接至**mysqld**时指定了标志CLIENT_FOUND_ROWS,对于UPDATE语句,mysql_affected_rows()将返回WHERE语句匹配的行数。
注意,使用REPLACE命令时,如果新行替代了旧行,mysql_affected_rows()返回2。这是因为,在该情况下,删除了重复行后插入了1行。
如果使用“INSERT ... ON DUPLICATE KEY UPDATE”来插入行,如果行是作为新行插入的,mysql_affected_rows()返回1,如果是更新了已有的行,返回2。
#### 25.2.3.2. mysql_autocommit()
my_bool mysql_autocommit(MYSQL *mysql, my_bool mode)
**描述**
如果模式为“1”,启用autocommit模式;如果模式为“0”,禁止autocommit模式。
**返回值**
如果成功,返回0,如果出现错误,返回非0值。
**错误**
无。
#### 25.2.3.3. mysql_change_user()
my_bool mysql_change_user(MYSQL *mysql, const char *user, const char *password, const char *db)
**描述**
更改用户,并使由db指定的数据库成为由mysql指定的连接上的默认数据库(当前数据库)。在后续查询中,对于不包含显式数据库区分符的表引用,该数据库是默认数据库。
如果不能确定已连接的用户或用户不具有使用数据库的权限,mysql_change_user()将失败。在这种情况下,不会改变用户和数据库。
如果不打算拥有默认数据库,可将db参数设置为NULL。
该命令总是会执行活动事务的ROLLBACK操作,关闭所有的临时表,解锁所有的锁定表,并复位状态,就像进行了新连接那样。即使未更改用户,也会出现该情况。
**返回值**
0表示成功,非0值表示出现错误。
**错误**
与从mysql_real_connect()获得的相同。
· CR_COMMANDS_OUT_OF_SYNC
以不恰当的顺序执行了命令。
· CR_SERVER_GONE_ERROR
MySQL服务器不可用。
· CR_SERVER_LOST
在查询过程中丢失了与服务器的连接。
· CR_UNKNOWN_ERROR
出现未知错误。
· ER_UNKNOWN_COM_ERROR
MySQL服务器未实施该命令(或许是较低版本的服务器)。
· ER_ACCESS_DENIED_ERROR
用户或密码错误。
· ER_BAD_DB_ERROR
数据库不存在。
· ER_DBACCESS_DENIED_ERROR
用户没有访问数据库的权限。
· ER_WRONG_DB_NAME
数据库名称过长。
**示例:**
if (mysql_change_user(&mysql, "user", "password", "new_database"))
{
fprintf(stderr, "Failed to change user. Error: %s\n",
mysql_error(&mysql));
}
#### 25.2.3.4. mysql_character_set_name()
const char *mysql_character_set_name(MYSQL *mysql)
**描述**
为当前连接返回默认的字符集。
**返回值**
默认字符集。
**错误**
无。
#### 25.2.3.5. mysql_close()
void mysql_close(MYSQL *mysql)
**描述**
关闭前面打开的连接。如果句柄是由mysql_init()或mysql_connect()自动分配的,mysql_close()还将解除分配由mysql指向的连接句柄。
**返回值**
无。
**错误**
无。
#### 25.2.3.6. mysql_commit()
my_bool mysql_commit(MYSQL *mysql)
**描述**
提交当前事务。
该函数的动作受completion_type系统变量的值控制。尤其是,如果completion_type的值为2,终结事务并关闭客户端连接后,服务器将执行释放操作。客户端程序应调用mysql_close(),从客户端一侧关闭连接。
**返回值**
如果成功,返回0,如果出现错误,返回非0值。
**错误**
无。
#### 25.2.3.7. mysql_connect()
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指针。
**返回值**
与mysql_real_connect()的相同。
**错误**
与mysql_real_connect()的相同。
#### 25.2.3.8. mysql_create_db()
int mysql_create_db(MYSQL *mysql, const char *db)
**描述**
创建由db参数命名的数据库。
该函数已过时。最好使用mysql_query()来发出SQL CREATE DATABASE语句。
**返回值**
如果数据库已成功创建,返回0,如果出现错误,返回非0值。
**错误**
· CR_COMMANDS_OUT_OF_SYNC
以不恰当的顺序执行了命令。
· CR_SERVER_GONE_ERROR
MySQL服务器不可用。
· CR_SERVER_LOST
在查询过程中,与服务器的连接丢失。
· CR_UNKNOWN_ERROR
出现未知错误。
**示例:**
if(mysql_create_db(&mysql, "my_database"))
{
fprintf(stderr, "Failed to create new database. Error: %s\n",
mysql_error(&mysql));
}
#### 25.2.3.9. mysql_data_seek()
void mysql_data_seek(MYSQL_RES *result, my_ulonglong offset)
**描述**
在查询结果集中寻找任意行。偏移值为行号,范围从0到mysql_num_rows(result)-1。
该函数要求结果集结构包含查询的所有结果,因此,so mysql_data_seek()仅应与mysql_store_result()联合使用,而不是与mysql_use_result()。
**返回值**
无。
**错误**
无。
#### 25.2.3.10. mysql_debug()
void mysql_debug(const char *debug)
**描述**
用给定的字符串执行DBUG_PUSH。mysql_debug()采用Fred Fish调试库。要想使用该函数,必须编译客户端库,使之支持调试功能。请参见[E.1节,“调试MySQL服务器”](# "E.1. Debugging a MySQL Server")。请参见[E.2节,“调试MySQL客户端”](# "E.2. Debugging a MySQL Client")。
**返回值**
无。
**错误**
无。
**示例:**
这里给出的调用将使客户端库在客户端机器的/tmp/client.trace中生成1个跟踪文件。
mysql_debug("d:t:O,/tmp/client.trace");
#### 25.2.3.11. mysql_drop_db()
int mysql_drop_db(MYSQL *mysql, const char *db)
**描述**
撤销由db参数命名数据库。
该函数已过时。最好使用mysql_query()来发出SQL DROP DATABASE语句
**返回值**
如果成功撤销了数据库,返回0。如果出现错误,返回非0值。
**错误**
· CR_COMMANDS_OUT_OF_SYNC
以不恰当的顺序执行了命令。
· CR_SERVER_GONE_ERROR
MySQL服务器不可用。
· CR_SERVER_LOST
在查询过程中,与服务器的连接丢失。
· CR_UNKNOWN_ERROR
出现未知错误。
**示例:**
if(mysql_drop_db(&mysql, "my_database"))
fprintf(stderr, "Failed to drop the database: Error: %s\n",
mysql_error(&mysql));
#### 25.2.3.12. mysql_dump_debug_info()
int mysql_dump_debug_info(MYSQL *mysql)
**描述**
指示服务器将一些调试信息写入日志。要想使之工作,已连接的用户必须具有SUPER权限。
**返回值**
如果命令成功,返回0。如果出现错误,返回非0值。
**错误**
· CR_COMMANDS_OUT_OF_SYNC
以不恰当的顺序执行了命令。
· CR_SERVER_GONE_ERROR
MySQL服务器不可用。
· CR_SERVER_LOST
在查询过程中,与服务器的连接丢失。
· CR_UNKNOWN_ERROR
出现未知错误。
#### 25.2.3.13. mysql_eof()
my_bool mysql_eof(MYSQL_RES *result)
**描述**
该函数已过时。应使用mysql_errno()或mysql_error()取而代之。
mysql_eof()确定是否已读取了结果集的最后1行。
如果通过成功调用mysql_store_result()获得了结果集,客户端将在1次操作中收到整个结果集。在该情况下,从mysql_fetch_row()返回的NULL总表示已到达结果集末尾,而且没必要调用mysql_eof()。与mysql_store_result()一起使用时,mysql_eof()总返回“真”。
另一方面,如果你使用mysql_use_result()来初始化结果集检索,当重复调用mysql_fetch_row()时,将逐个地从服务器获取结果集的行。由于在该过程中,可能出现连接上的错误,从mysql_fetch_row()返回的NULL值不一定表示已正常地抵达结果集末尾。在该情况下,可以使用mysql_eof()来判定出现了什么情况。如果抵达结果集末尾,mysql_eof()返回非0值,如果出现错误,返回0。
从历史的角度上看,mysql_eof()在日期上早于标准的MySQL错误函数mysql_errno()和mysql_error()。由于这类错误函数提供了相同的信息,它们优先于已过时的mysql_eof()。事实上,它们提供了更多信息,这是因为,mysql_eof()仅返回布尔值,错误函数能够在出现错误时指明错误的原因。
**返回值**
如果未出现错误,返回0。如果抵达结果集的末尾,返回非0值。
**错误**
无。
**示例:**
在下面的示例中,介绍了使用mysql_eof()的方法:
mysql_query(&mysql,"SELECT * FROM some_table");
result = mysql_use_result(&mysql);
while((row = mysql_fetch_row(result)))
{
// do something with data
}
if(!mysql_eof(result)) // mysql_fetch_row() failed due to an error
{
fprintf(stderr, "Error: %s\n", mysql_error(&mysql));
}
但是,你也能使用标准的MySQL错误函数实现相同的结果:
mysql_query(&mysql,"SELECT * FROM some_table");
result = mysql_use_result(&mysql);
while((row = mysql_fetch_row(result)))
{
// do something with data
}
if(mysql_errno(&mysql)) // mysql_fetch_row() failed due to an error
{
fprintf(stderr, "Error: %s\n", mysql_error(&mysql));
}
#### 25.2.3.14. mysql_errno()
unsigned int mysql_errno(MYSQL *mysql)
**描述**
对于由mysql指定的连接,mysql_errno()返回最近调用的API函数的错误代码,该函数调用可能成功也可能失败。“0”返回值表示未出现错误。在MySQL errmsg.h头文件中,列出了客户端错误消息编号。在[附录B:](#)[_错误代码和消息_](# "Appendix B. Error Codes and Messages")中,也列出了这些错误。
注意,如果成功,某些函数,如mysql_fetch_row()等,不会设置mysql_errno()。
经验规则是,如果成功,所有向服务器请求信息的函数均会复位mysql_errno()。
**返回值**
如果失败,返回上次mysql__xxx_()调用的错误代码。“0”表示未出现错误。
**错误**
无。
#### 25.2.3.15. mysql_error()
const char *mysql_error(MYSQL *mysql)
**描述**
对于由mysql指定的连接,对于失败的最近调用的API函数,mysql_error()返回包含错误消息的、由Null终结的字符串。如果该函数未失败,mysql_error()的返回值可能是以前的错误,或指明无错误的空字符串。
经验规则是,如果成功,所有向服务器请求信息的函数均会复位mysql_error()。
对于复位mysql_errno()的函数,下述两个测试是等效的:
if(mysql_errno(&mysql))
{
// an error occurred
}
if(mysql_error(&mysql)[0] != '\0')
{
// an error occurred
}
通过重新编译MySQL客户端库,可以更改客户端错误消息的语言。目前,能够选择数种语言显示错误消息,请参见[5.10.2节,“设置错误消息语言”](# "5.10.2. Setting the Error Message Language")。
**返回值**
返回描述错误的、由Null终结的字符串。如果未出现错误,返回空字符串。
**错误**
无。
#### 25.2.3.16. mysql_escape_string()
应使用mysql_real_escape_string()取而代之!
该函数与mysql_real_escape_string()等同,但mysql_real_escape_string()会将连接处理程序作为其第1个参量,并按照当前字符集对字符串进行转义处理。mysql_escape_string()不采用连接参量,而且不考虑当前字符集设置。
#### 25.2.3.17. 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。
**错误**
无。
**示例:**
MYSQL_FIELD *field;
while((field = mysql_fetch_field(result)))
{
printf("field name %s\n", field->name);
}
#### 25.2.3.18. mysql_fetch_field_direct()
MYSQL_FIELD *mysql_fetch_field_direct(MYSQL_RES *result, unsigned int fieldnr)
**描述**
给定结果集内某1列的字段编号fieldnr,以MYSQL_FIELD结构形式返回列的字段定义。可以使用该函数检索任意列的定义。Fieldnr的值应在从0到mysql_num_fields(result)-1的范围内。
**返回值**
对于指定列,返回MYSQL_FIELD结构。
**错误**
无。
**示例:**
unsigned int num_fields;
unsigned int i;
MYSQL_FIELD *field;
num_fields = mysql_num_fields(result);
for(i = 0; i < num_fields; i++)
{
field = mysql_fetch_field_direct(result, i);
printf("Field %u is %s\n", i, field->name);
}
#### 25.2.3.19. mysql_fetch_fields()
MYSQL_FIELD *mysql_fetch_fields(MYSQL_RES *result)
**描述**
对于结果集,返回所有MYSQL_FIELD结构的数组。每个结构提供了结果集中1列的字段定义。
**返回值**
关于结果集所有列的MYSQL_FIELD结构的数组。
**错误**
无。
**示例:**
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);
}
#### 25.2.3.20. mysql_fetch_lengths()
unsigned long *mysql_fetch_lengths(MYSQL_RES *result)
**描述**
返回结果集内当前行的列的长度。如果打算复制字段值,该长度信息有助于优化,这是因为,你能避免调用strlen()。此外,如果结果集包含二进制数据,必须使用该函数来确定数据的大小,原因在于,对于包含Null字符的任何字段,strlen()将返回
- 前言
- 1. 一般信息
- 2. 安装MySQL
- 3. 教程
- 4. MySQL程序概述
- 5. 数据库管理
- 6. MySQL中的复制
- 7. 优化
- 8. 客户端和实用工具程序
- 9. 语言结构
- 10. 字符集支持
- 11. 列类型
- 12. 函数和操作符
- 13. SQL语句语法
- 14. 插件式存储引擎体系结构
- 15. 存储引擎和表类型
- 16. 编写自定义存储引擎
- 17. MySQL簇
- 18. 分区
- 19. MySQL中的空间扩展
- 20. 存储程序和函数
- 21. 触发程序
- 22. 视图
- 23. INFORMATION_SCHEMA信息数据库
- 24. 精度数学
- 25. API和库
- 26. 连接器
- 27. 扩展MySQL
- A. 问题和常见错误
- B. 错误代码和消息
- C. 感谢
- D. MySQL变更史
- E. 移植到其他系统
- F. 环境变量
- G. MySQL正则表达式
- H. MySQL中的限制
- I. 特性限制
- J. GNU通用公共许可
- K. MySQL FLOSS许可例外
- 索引