Chinaunix首页 | 论坛 | 博客
  • 博客访问: 92510385
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类: Mysql/postgreSQL

2008-05-12 15:12:58

25.2.7.6. mysql_stmt_close()

my_bool mysql_stmt_close(MYSQL_STMT *)

描述

关闭预处理语句。此外,mysql_stmt_close()还会取消由“stmt”指向的语句句柄分配。

如果当前语句已挂起或未读取结果,该函数将取消它们,以便能执行下一个查询,

返回值

如果成功释放了语句,返回0。如果出现错误,返回非0值。

错误

·         CR_SERVER_GONE_ERROR

MySQL服务器不可用。

·         CR_UNKNOWN_ERROR

出现未知错误。

示例:

关于mysql_stmt_close()的用法,请参见25.2.7.10节,“mysql_stmt_execute()”中给出的示例。

25.2.7.7. mysql_stmt_data_seek()

void mysql_stmt_data_seek(MYSQL_STMT *stmt, my_ulonglong offset)

描述

查找语句结果集中的任意行。偏移量为行编号,应位于从0mysql_stmt_num_rows(stmt)-1的范围内。

该函数要求语句结果集结构包含上次执行查询的全部结果,这样,mysql_stmt_data_seek()就能与mysql_stmt_store_result()一起使用。

返回值

无。

错误

无。

25.2.7.8. mysql_stmt_errno()

unsigned int mysql_stmt_errno(MYSQL_STMT *stmt)

描述

对于由stmt指定的语句,mysql_stmt_errno()将返回最近调用的语句API函数的错误代码,该函数或成功或失败。0”返回值表示未出现错误。在MySQL errmsg.h头文件中列出了客户端错误消息编号。在mysqld_error.h中,列出了服务器错误消息。此外,在附录B:错误代码和消息中,也列出了错误消息。

返回值

错误代码值。如果未出现错误,返回0

错误

无。

25.2.7.9. mysql_stmt_error()

const char *mysql_stmt_error(MYSQL_STMT *stmt)

描述

对于由stmt指定的语句,mysql_stmt_error()返回由Null终结的字符串,该字符串包含最近调用的语句API函数的错误消息,该函数或成功或失败。如果未出现错误,返回空字符串("")。这意味着下述两个测试是等效的:

 
if (mysql_stmt_errno(stmt))
{
  // an error occurred
}
 
if (mysql_stmt_error(stmt)[0])
{
  // an error occurred
}

通过重新编译MySQL客户端库,可更改客户端错误消息的语言。目前,能够选择数种语言之一显示错误消息。

返回值

描述了错误的字符串。如果未出现错误,返回空字符串。

错误

无。

25.2.7.10. mysql_stmt_execute()

int mysql_stmt_execute(MYSQL_STMT *stmt)

描述

mysql_stmt_execute()执行与语句句柄相关的预处理查询。在该调用期间,将当前绑定的参数标记符的值发送到服务器,服务器用新提供的数据替换标记符。

如果语句是UPDATEDELETEINSERT,通过调用mysql_stmt_affected_rows(),可发现更改、删除或插入的总行数。如果这是诸如SELECT等能生成结果集的语句,调用任何其他能导致查询处理的函数之前,必须调用mysql_stmt_fetch()来获取数据。关于如何获取结果的更多信息,请参见25.2.7.11节,“mysql_stmt_fetch()”

对于生成结果集的语句,执行语句之前,可通过调用mysql_stmt_attr_set()请求mysql_stmt_execute()为语句打开光标。如果多次执行某一语句,在打开新的光标前,mysql_stmt_execute()将关闭任何已打开的光标。

返回值

如果执行成功,返回0。如果出现错误,返回非0值。

错误

·         CR_COMMANDS_OUT_OF_SYNC

以不恰当的顺序执行了命令。

·         CR_OUT_OF_MEMORY

内存溢出。

·         CR_SERVER_GONE_ERROR

MySQL服务器不可用。

·         CR_SERVER_LOST

在查询过程中,与服务器的连接丢失。

·         CR_UNKNOWN_ERROR

出现未知错误。

示例:

在下面的示例中,介绍了使用mysql_stmt_init()mysql_stmt_prepare()mysql_stmt_param_count()mysql_stmt_bind_param()mysql_stmt_execute()、以及mysql_stmt_affected_rows()创建和填充表的方法。假定mysql变量具有有效的连接句柄。

#define STRING_SIZE 50
 
#define DROP_SAMPLE_TABLE "DROP TABLE IF EXISTS test_table"
#define CREATE_SAMPLE_TABLE "CREATE TABLE test_table(col1 INT,\
                                                 col2 VARCHAR(40),\
                                                 col3 SMALLINT,\
                                                 col4 TIMESTAMP)"
#define INSERT_SAMPLE "INSERT INTO test_table(col1,col2,col3) VALUES(?,?,?)"
 
MYSQL_STMT    *stmt;
MYSQL_BIND    bind[3];
my_ulonglong  affected_rows;
int           param_count;
short         small_data;
int           int_data;
char          str_data[STRING_SIZE];
unsigned long str_length;
my_bool       is_null;
 
if (mysql_query(mysql, DROP_SAMPLE_TABLE))
{
  fprintf(stderr, " DROP TABLE failed\n");
  fprintf(stderr, " %s\n", mysql_error(mysql));
  exit(0);
}
 
if (mysql_query(mysql, CREATE_SAMPLE_TABLE))
{
  fprintf(stderr, " CREATE TABLE failed\n");
  fprintf(stderr, " %s\n", mysql_error(mysql));
  exit(0);
}
 
/* Prepare an INSERT query with 3 parameters */
/* (the TIMESTAMP column is not named; the server */
/*  sets it to the current date and time) */
stmt = mysql_stmt_init(mysql);
if (!stmt)
{
  fprintf(stderr, " mysql_stmt_init(), out of memory\n");
  exit(0);
}
if (mysql_stmt_prepare(stmt, INSERT_SAMPLE, strlen(INSERT_SAMPLE)))
{
  fprintf(stderr, " mysql_stmt_prepare(), INSERT failed\n");
  fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
  exit(0);
}
fprintf(stdout, " prepare, INSERT successful\n");
 
/* Get the parameter count from the statement */
param_count= mysql_stmt_param_count(stmt);
fprintf(stdout, " total parameters in INSERT: %d\n", param_count);
 
if (param_count != 3) /* validate parameter count */
{
  fprintf(stderr, " invalid parameter count returned by MySQL\n");
  exit(0);
}
 
/* Bind the data for all 3 parameters */
 
memset(bind, 0, sizeof(bind));
 
/* INTEGER PARAM */
/* This is a number type, so there is no need to specify buffer_length */
bind[0].buffer_type= MYSQL_TYPE_LONG;
bind[0].buffer= (char *)&int_data;
bind[0].is_null= 0;
bind[0].length= 0;
 
/* STRING PARAM */
bind[1].buffer_type= MYSQL_TYPE_STRING;
bind[1].buffer= (char *)str_data;
bind[1].buffer_length= STRING_SIZE;
bind[1].is_null= 0;
bind[1].length= &str_length;
 
/* SMALLINT PARAM */
bind[2].buffer_type= MYSQL_TYPE_SHORT;
bind[2].buffer= (char *)&small_data;
bind[2].is_null= &is_null;
bind[2].length= 0;
 
/* Bind the buffers */
if (mysql_stmt_bind_param(stmt, bind))
{
  fprintf(stderr, " mysql_stmt_bind_param() failed\n");
  fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
  exit(0);
}
 
/* Specify the data values for the first row */
int_data= 10;             /* integer */
strncpy(str_data, "MySQL", STRING_SIZE); /* string  */
str_length= strlen(str_data);
 
/* INSERT SMALLINT data as NULL */
is_null= 1;
 
/* Execute the INSERT statement - 1*/
if (mysql_stmt_execute(stmt))
{
  fprintf(stderr, " mysql_stmt_execute(), 1 failed\n");
  fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
  exit(0);
}
 
/* Get the total number of affected rows */
affected_rows= mysql_stmt_affected_rows(stmt);
fprintf(stdout, " total affected rows(insert 1): %lu\n",
                (unsigned long) affected_rows);
 
if (affected_rows != 1) /* validate affected rows */
{
  fprintf(stderr, " invalid affected rows by MySQL\n");
  exit(0);
}
 
/* Specify data values for second row, then re-execute the statement */
int_data= 1000;
strncpy(str_data, "The most popular Open Source database", STRING_SIZE);
str_length= strlen(str_data);
small_data= 1000;         /* smallint */
is_null= 0;               /* reset */
 
/* Execute the INSERT statement - 2*/
if (mysql_stmt_execute(stmt))
{
  fprintf(stderr, " mysql_stmt_execute, 2 failed\n");
  fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
  exit(0);
}
 
/* Get the total rows affected */
affected_rows= mysql_stmt_affected_rows(stmt);
fprintf(stdout, " total affected rows(insert 2): %lu\n",
                (unsigned long) affected_rows);
 
if (affected_rows != 1) /* validate affected rows */
{
  fprintf(stderr, " invalid affected rows by MySQL\n");
  exit(0);
}
 
/* Close the statement */
if (mysql_stmt_close(stmt))
{
  fprintf(stderr, " failed while closing the statement\n");
  fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
  exit(0);
}

注释:关于使用预处理语句函数的完整示例,请参见文件tests/mysql_client_test.c。该文件可从MySQL源码分发版获得,或从BitKeeper源码仓库获得。

25.2.7.11. mysql_stmt_fetch()

int mysql_stmt_fetch(MYSQL_STMT *stmt)

描述

mysql_stmt_fetch()返回结果集中的下一行。仅能当结果集存在时调用它,也就是说,调用了能创建结果集的mysql_stmt_execute()之后,或当mysql_stmt_execute()对整个结果集即行缓冲处理后调用了mysql_stmt_store_result()

使用mysql_stmt_bind_result()绑定的缓冲,mysql_stmt_fetch()返回行数据。对于当前列集合中的所有列,它将返回缓冲内的数据,并将长度返回到长度指针。

调用mysql_stmt_fetch()之前,应用程序必须绑定所有列。

如果获取的数据值是NULL值,对应MYSQL_BIND结构的*is_null值将包含TRUE (1)。否则,将根据应用程序指定的缓冲类型,在*buffer*length内返回数据及其长度。每个数值类型和临时类型都有固定的长度,请参见下面的表格。字符串类型的长度取决于由data_length指明的实际数据值的长度。

类型

长度

MYSQL_TYPE_TINY

1

MYSQL_TYPE_SHORT

2

MYSQL_TYPE_LONG

4

MYSQL_TYPE_LONGLONG

8

MYSQL_TYPE_FLOAT

4

MYSQL_TYPE_DOUBLE

8

MYSQL_TYPE_TIME

sizeof(MYSQL_TIME)

MYSQL_TYPE_DATE

sizeof(MYSQL_TIME)

MYSQL_TYPE_DATETIME

sizeof(MYSQL_TIME)

MYSQL_TYPE_STRING

data length

MYSQL_TYPE_BLOB

data_length

返回值

返回值

描述

0

成功,数据被提取到应用程序数据缓冲区。

1

出现错误。通过调用mysql_stmt_errno()mysql_stmt_error(),可获取错误代码和错误消息。

MYSQL_NO_DATA

不存在行/数据。

MYSQL_DATA_TRUNCATED

出现数据截短。

不返回MYSQL_DATA_TRUNCATED,除非用mysql_options()启用了截短通报功能。返回该值时,为了确定截短的参数是哪个,可检查MYSQL_BIND参数结构的错误成员。

错误

·         CR_COMMANDS_OUT_OF_SYNC

以不恰当的顺序执行了命令。

·         CR_OUT_OF_MEMORY

内存溢出。

·         CR_SERVER_GONE_ERROR

MySQL服务器不可用。

·         CR_SERVER_LOST

在查询过程中,与服务器的连接丢失。

·         CR_UNKNOWN_ERROR

出现未知错误。

·         CR_UNSUPPORTED_PARAM_TYPE

缓冲类型为MYSQL_TYPE_DATEMYSQL_TYPE_TIMEMYSQL_TYPE_DATETIME、或MYSQL_TYPE_TIMESTAMP,但数据类型不是DATETIMEDATETIME、或TIMESTAMP

·         mysql_stmt_bind_result()返回所有其他不支持的转换错误。

示例:

在下面的示例中,介绍了使用mysql_stmt_result_metadata()mysql_stmt_bind_result()mysql_stmt_fetch()从表中获取数据的方法。(在本示例中,将检索在25.2.7.10节,“mysql_stmt_execute()”一节的示例中插入的两行内容。假定mysql变量具有有效的连接句柄。

#define STRING_SIZE 50
 
#define SELECT_SAMPLE "SELECT col1, col2, col3, col4 FROM test_table"
 
MYSQL_STMT    *stmt;
MYSQL_BIND    bind[4];
MYSQL_RES     *prepare_meta_result;
MYSQL_TIME    ts;
unsigned long length[4];
int           param_count, column_count, row_count;
short         small_data;
int           int_data;
char          str_data[STRING_SIZE];
my_bool       is_null[4];
 
/* Prepare a SELECT query to fetch data from test_table */
stmt = mysql_stmt_init(mysql);
if (!stmt)
{
  fprintf(stderr, " mysql_stmt_init(), out of memory\n");
  exit(0);
}
if (mysql_stmt_prepare(stmt, SELECT_SAMPLE, strlen(SELECT_SAMPLE)))
{
  fprintf(stderr, " mysql_stmt_prepare(), SELECT failed\n");
  fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
  exit(0);
}
fprintf(stdout, " prepare, SELECT successful\n");
 
/* Get the parameter count from the statement */
param_count= mysql_stmt_param_count(stmt);
fprintf(stdout, " total parameters in SELECT: %d\n", param_count);
 
if (param_count != 0) /* validate parameter count */
{
  fprintf(stderr, " invalid parameter count returned by MySQL\n");
  exit(0);
}
 
/* Fetch result set meta information */
prepare_meta_result = mysql_stmt_result_metadata(stmt);
if (!prepare_meta_result)
{
  fprintf(stderr,
         " mysql_stmt_result_metadata(), returned no meta information\n");
  fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
  exit(0);
}
 
/* Get total columns in the query */
column_count= mysql_num_fields(prepare_meta_result);
fprintf(stdout, " total columns in SELECT statement: %d\n", column_count);
 
if (column_count != 4) /* validate column count */
{
  fprintf(stderr, " invalid column count returned by MySQL\n");
  exit(0);
}
 
/* Execute the SELECT query */
if (mysql_stmt_execute(stmt))
{
  fprintf(stderr, " mysql_stmt_execute(), failed\n");
  fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
  exit(0);
}
 
/* Bind the result buffers for all 4 columns before fetching them */
 
memset(bind, 0, sizeof(bind));
 
/* INTEGER COLUMN */
bind[0].buffer_type= MYSQL_TYPE_LONG;
bind[0].buffer= (char *)&int_data;
bind[0].is_null= &is_null[0];
bind[0].length= &length[0];
 
/* STRING COLUMN */
bind[1].buffer_type= MYSQL_TYPE_STRING;
bind[1].buffer= (char *)str_data;
bind[1].buffer_length= STRING_SIZE;
bind[1].is_null= &is_null[1];
bind[1].length= &length[1];
 
/* SMALLINT COLUMN */
bind[2].buffer_type= MYSQL_TYPE_SHORT;
bind[2].buffer= (char *)&small_data;
bind[2].is_null= &is_null[2];
bind[2].length= &length[2];
 
/* TIMESTAMP COLUMN */
bind[3].buffer_type= MYSQL_TYPE_TIMESTAMP;
bind[3].buffer= (char *)&ts;
bind[3].is_null= &is_null[3];
bind[3].length= &length[3];
 
/* Bind the result buffers */
if (mysql_stmt_bind_result(stmt, bind))
{
  fprintf(stderr, " mysql_stmt_bind_result() failed\n");
  fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
  exit(0);
}
 
/* Now buffer all results to client */
if (mysql_stmt_store_result(stmt))
{
  fprintf(stderr, " mysql_stmt_store_result() failed\n");
  fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
  exit(0);
}
 
/* Fetch all rows */
row_count= 0;
fprintf(stdout, "Fetching results ...\n");
while (!mysql_stmt_fetch(stmt))
{
  row_count++;
  fprintf(stdout, "  row %d\n", row_count);
 
  /* column 1 */
  fprintf(stdout, "   column1 (integer)  : ");
  if (is_null[0])
    fprintf(stdout, " NULL\n");
  else
    fprintf(stdout, " %d(%ld)\n", int_data, length[0]);
 
  /* column 2 */
  fprintf(stdout, "   column2 (string)   : ");
  if (is_null[1])
    fprintf(stdout, " NULL\n");
  else
    fprintf(stdout, " %s(%ld)\n", str_data, length[1]);
 
  /* column 3 */
  fprintf(stdout, "   column3 (smallint) : ");
  if (is_null[2])
    fprintf(stdout, " NULL\n");
  else
    fprintf(stdout, " %d(%ld)\n", small_data, length[2]);
 
  /* column 4 */
  fprintf(stdout, "   column4 (timestamp): ");
  if (is_null[3])
    fprintf(stdout, " NULL\n");
  else
    fprintf(stdout, " %04d-%02d-%02d %02d:%02d:%02d (%ld)\n",
                     ts.year, ts.month, ts.day,
                     ts.hour, ts.minute, ts.second,
                     length[3]);
  fprintf(stdout, "\n");
}
 
/* Validate rows fetched */
fprintf(stdout, " total rows fetched: %d\n", row_count);
if (row_count != 2)
{
  fprintf(stderr, " MySQL failed to return all rows\n");
  exit(0);
}
 
/* Free the prepared result metadata */
mysql_free_result(prepare_meta_result);
 
 
/* Close the statement */
if (mysql_stmt_close(stmt))
{
  fprintf(stderr, " failed while closing the statement\n");
  fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
  exit(0);
}

25.2.7.12. mysql_stmt_fetch_column()

int mysql_stmt_fetch_column(MYSQL_STMT *stmt, MYSQL_BIND *bind, unsigned int column, unsigned long offset)

描述

从当前结果集行获取1列。“bind”提供了应将数据置于其中的缓冲。其设置方法应与设置mysql_stmt_bind_result()的相同。column”指明了将获取哪个列。第1列编号为0offset”是数据值内的偏移量,将从该处开始检索数据。可将其用于获取碎片形式的数据值。值开始部分的偏移量为0

返回值

如果成功获取了值,返回0。如果出现错误,返回非0值。

错误

·         CR_INVALID_PARAMETER_NO

Invalid column number.

·         CR_NO_DATA

已抵达结果集的末尾。

25.2.7.13. mysql_stmt_field_count()

unsigned int mysql_stmt_field_count(MYSQL_STMT *stmt)

描述

为语句处理程序返回关于最近语句的行数。对于诸如INSERTDELETE等不生成结果集的语句,该值为0

通过调用mysql_stmt_prepare()准备好了语句后,可调用mysql_stmt_field_count()

返回值

表示结果集中行数的无符号整数。

错误

无。

25.2.7.14. mysql_stmt_free_result()

my_bool mysql_stmt_free_result(MYSQL_STMT *stmt)

描述

释放与执行预处理语句生成的结果集有关的内存。对于该语句,如果存在打开的光标,mysql_stmt_free_result()将关闭它。

返回值

如果成功释放了结果集,返回0。如果出现错误,返回非0值。

错误

25.2.7.15. mysql_stmt_init()

MYSQL_STMT *mysql_stmt_init(MYSQL *mysql)

描述

创建MYSQL_STMT句柄。对于该句柄,应使用mysql_stmt_close(MYSQL_STMT *)释放。

返回值

成功时,返回指向MYSQL_STMT结构的指针。如果内存溢出,返回NULL

错误

·         CR_OUT_OF_MEMORY

内存溢出。

25.2.7.16. mysql_stmt_insert_id()

my_ulonglong mysql_stmt_insert_id(MYSQL_STMT *stmt)

描述

返回预处理INSERTUPDATE语句AUTO_INCREMENT列生成的值。在包含AUTO_INCREMENT字段的表上执行了预处理INSERT语句后,使用该函数。

更多信息,请参见25.2.3.36节,“mysql_insert_id()”

返回值

为在执行预处理语句期间自动生成或明确设置的AUTO_INCREMENT列返回值,或LAST_INSERT_ID(expr)函数生成的值。如果语句未设置AUTO_INCREMENT值,返回值不确定。

错误

无。

25.2.7.17. mysql_stmt_num_rows()

my_ulonglong mysql_stmt_num_rows(MYSQL_STMT *stmt)

描述

返回结果集中的行数。

mysql_stmt_num_rows()的用法取决于是否使用了mysql_stmt_store_result()来对语句句柄中的全部结果集进行了缓冲处理。

如果使用了mysql_stmt_store_result(),可立刻调用mysql_stmt_num_rows()

返回值

结果集中的行数。

错误

无。

25.2.7.18. mysql_stmt_param_count()

unsigned long mysql_stmt_param_count(MYSQL_STMT *stmt)

描述

返回预处理语句中参数标记符的数目。

返回值

表示语句中参数数目的无符号长整数。

错误

无。

示例:

关于mysql_stmt_param_count()的用法,请参见25.2.7.10节,“mysql_stmt_execute()”中给出的示例。

25.2.7.19. mysql_stmt_param_metadata()

MYSQL_RES *mysql_stmt_param_metadata(MYSQL_STMT *stmt)

该函数目前不做任何事。

描述

返回值

错误

25.2.7.20. mysql_stmt_prepare()

int mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, unsigned long length)

描述

给定mysql_stmt_init()返回的语句句柄,准备字符串查询指向的SQL语句,并返回状态值。字符串长度应由“length”参量给出。字符串必须包含1SQL语句。不应为语句添加终结用分号(;)\g

通过将问号字符“?”嵌入到SQL字符串的恰当位置,应用程序可包含SQL语句中的一个或多个参数标记符。

标记符仅在SQL语句中的特定位置时才是合法的。例如,它可以在INSERT语句的VALUES()列表中(为行指定列值),或与WHERE子句中某列的比较部分(用以指定比较值)。但是,对于ID(例如表名或列名),不允许使用它们,不允许指定二进制操作符(如等于号“=”)的操作数。后一个限制是有必要的,原因在于,无法确定参数类型。一般而言,参数仅在DML(数据操作语言)语句中才是合法的,在DDL(数据定义语言)语句中不合法。

执行语句之前,必须使用mysql_stmt_bind_param(),将参数标记符与应用程序变量绑定在一起。

返回值

如果成功处理了语句,返回0。如果出现错误,返回非0值。

错误

·         CR_COMMANDS_OUT_OF_SYNC

以不恰当的顺序执行了命令。

·         CR_OUT_OF_MEMORY

内存溢出。

·         CR_SERVER_GONE_ERROR

MySQL服务器不可用。

·         CR_SERVER_LOST

查询过程中,与服务器的连接丢失。

·         CR_UNKNOWN_ERROR

出现未知错误。

如果准备操作失败(即mysql_stmt_prepare()返回非0值),可通过调用mysql_stmt_error()获取错误消息。

示例:

关于mysql_stmt_prepare()的用法,请参见25.2.7.10节,“mysql_stmt_execute()”中给出的示例。

25.2.7.21. mysql_stmt_reset()

my_bool mysql_stmt_reset(MYSQL_STMT *stmt)

描述

在客户端和服务器上,将预处理语句复位为完成准备后的状态。主要用于复位用mysql_stmt_send_long_data()发出的数据。对于语句,任何已打开的光标将被关闭。

要想重新准备用于另一查询的语句,可使用mysql_stmt_prepare()

返回值

如果语句成功复位,返回0。如果出现错误,返回非0值。

错误

·         CR_COMMANDS_OUT_OF_SYNC

以不恰当的顺序执行了命令。

·         CR_SERVER_GONE_ERROR

MySQL服务器不可用。

·         CR_SERVER_LOST

查询过程中,与服务器的连接丢失。

·         CR_UNKNOWN_ERROR

出现未知错误。

25.2.7.22. mysql_stmt_result_metadata()

MYSQL_RES *mysql_stmt_result_metadata(MYSQL_STMT *stmt)

描述

如果传递给mysql_stmt_prepare()的语句能够成生结果集,mysql_stmt_result_metadata()将以指针的形式返回结果集元数据,该指针指向MYSQL_RES结构,可用于处理元信息,如总的字段数以及单独的字段信息。该结果集指针可作为参量传递给任何基于字段且用于处理结果集元数据的API函数,如:

·         mysql_num_fields()

·         mysql_fetch_field()

·         mysql_fetch_field_direct()

·         mysql_fetch_fields()

·         mysql_field_count()

·         mysql_field_seek()

·         mysql_field_tell()

·         mysql_free_result()

完成操作后,应释放结果集结构,可通过将其传递给mysql_free_result()完成。它与释放通过mysql_store_result()调用获得的结果集的方法类似。

mysql_stmt_result_metadata()返回的结果集仅包含元数据。不含任何行结果。与mysql_stmt_fetch()一起使用语句句柄,可获取行。

返回值

MYSQL_RES结果结构。如果不存在关于预处理查询的任何元信息,返回NULL

错误

·         CR_OUT_OF_MEMORY

内存溢出。

·         CR_UNKNOWN_ERROR

出现未知错误。

示例:

关于mysql_stmt_result_metadata()的用法,请参见25.2.7.11节,“mysql_stmt_fetch()”中给出的示例。

25.2.7.23. mysql_stmt_row_seek()

MYSQL_ROW_OFFSET mysql_stmt_row_seek(MYSQL_STMT *stmt, MYSQL_ROW_OFFSET offset)

描述

将行光标设置到语句结果集中的任意行。“offset”值是行偏移的值,行偏移应是mysql_stmt_row_tell()mysql_stmt_row_seek()返回的值。该值不是行编号,如果打算按编号查找结果集中的行,可使用mysql_stmt_data_seek()取而代之。

该函数要求结果集结构包含查询的全部结果,以便mysql_stmt_row_seek()能够仅与mysql_stmt_store_result()一起使用。

返回值

行光标的前一个值。可以将该值换递给后续的mysql_stmt_row_seek()调用。

错误

无。

25.2.7.24. mysql_stmt_row_tell()

MYSQL_ROW_OFFSET mysql_stmt_row_tell(MYSQL_STMT *stmt)

描述

返回针对前一个mysql_stmt_fetch()的行光标的当前位置。该值可用作mysql_stmt_row_seek()的参量。

仅应在mysql_stmt_store_result()之后使用mysql_stmt_row_tell()

返回值

行光标的当前偏移量。

错误

无。

25.2.7.25. mysql_stmt_send_long_data()

my_bool mysql_stmt_send_long_data(MYSQL_STMT *stmt, unsigned int parameter_number, const char *data, unsigned long length)

描述

允许应用程序分段地(分块)将参数数据发送到服务器。可以多次调用该函数,以便发送关于某一列的字符或二进制数据的不同部分,列必须是TEXTBLOB数据类型之一。

“parameter_number”指明了与数据关联的参数。参数从0开始编号。“data”是指向包含将要发送的数据的缓冲区的指针,length”指明了缓冲区内的字节数。

注释:自上一个mysql_stmt_execute()mysql_stmt_reset()后,对于与mysql_stmt_send_long_data()一起使用的所有参数,下一个mysql_stmt_execute()调用将忽略绑定缓冲。

如果希望复位/忽略已发送的数据,可使用mysql_stmt_reset()。请参见25.2.7.21节,“mysql_stmt_reset()”

返回值

如果成功地将数据发送到服务器,返回0。如果出现错误,返回非0值。

错误

·         CR_COMMANDS_OUT_OF_SYNC

以不恰当的顺序执行了命令。

·         CR_SERVER_GONE_ERROR

MySQL服务器不可用。

·         CR_OUT_OF_MEMORY

内存溢出。

·         CR_UNKNOWN_ERROR

出现未知错误。

示例:

在下面的示例中,介绍了以信息块形式为TEXT列发送数据的方法。它会将数据值“MySQL,最流行的开放源码数据库”插入到text_column列中。假定mysql变量具有有效的连接句柄。

#define INSERT_QUERY "INSERT INTO test_long_data(text_column) VALUES(?)"
 
MYSQL_BIND bind[1];
long       length;
 
smtt = mysql_stmt_init(mysql);
if (!stmt)
{
  fprintf(stderr, " mysql_stmt_init(), out of memory\n");
  exit(0);
}
if (mysql_stmt_prepare(stmt, INSERT_QUERY, strlen(INSERT_QUERY)))
{
  fprintf(stderr, "\n mysql_stmt_prepare(), INSERT failed");
  fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
  exit(0);
}
 memset(bind, 0, sizeof(bind));
 bind[0].buffer_type= MYSQL_TYPE_STRING;
 bind[0].length= &length;
 bind[0].is_null= 0;
 
/* Bind the buffers */
if (mysql_stmt_bind_param(stmt, bind))
{
  fprintf(stderr, "\n param bind failed");
  fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
  exit(0);
}
 
 /* Supply data in chunks to server */
 if (!mysql_stmt_send_long_data(stmt,0,"MySQL",5))
{
  fprintf(stderr, "\n send_long_data failed");
  fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
  exit(0);
}
 
 /* Supply the next piece of data */
 if (mysql_stmt_send_long_data(stmt,0," - The most popular Open Source database",40))
{
  fprintf(stderr, "\n send_long_data failed");
  fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
  exit(0);
}
 
 /* Now, execute the query */
 if (mysql_stmt_execute(stmt))
{
  fprintf(stderr, "\n mysql_stmt_execute failed");
  fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
  exit(0);
}

25.2.7.26. mysql_stmt_sqlstate()

const char *mysql_stmt_sqlstate(MYSQL_STMT *stmt)

描述

对于由stmt指定的语句,mysql_stmt_sqlstate()返回由Null终结的字符串,该字符串包含针对最近调用预处理语句API函数的SQLSTATE错误代码,该函数或成功或失败。错误代码由5个字符构成。"00000"表示“无错误”。这些值由ANSI SQLODBC指定。关于可能值的列表,请参见附录B:错误代码和消息

注意,并非所有的MySQL错误均会被映射到SQLSTATE代码。值"HY000"(一般错误)用于未映射的错误。

返回值

包含SQLSTATE错误代码、由Null终结的字符串。

25.2.7.27. mysql_stmt_store_result()

int mysql_stmt_store_result(MYSQL_STMT *stmt)

描述

对于成功生成结果集的所有语句(SELECTSHOWDESCRIBEEXPLAIN),而且仅当你打算对客户端的全部结果集进行缓冲处理时,必须调用mysql_stmt_store_result(),以便后续的mysql_stmt_fetch()调用能返回缓冲数据。

对于其他语句,没有必要调用mysql_stmt_store_result(),但如果调用了它,也不会造成任何伤害或导致任何性能问题。通过检查mysql_stmt_result_metadata()是否返回NULL,可检测语句是否生成了结果集。更多信息,请参见25.2.7.22节,“mysql_stmt_result_metadata()”

注释:默认情况下,对于mysql_stmt_store_result()中的所有列,MySQL不计算MYSQL_FIELD->max_length,这是因为,计算它会显著降低mysql_stmt_store_result()的性能,而且大多数应用程序不需要max_length。如果打算更新max_length可通过调用mysql_stmt_attr_set(MYSQL_STMT, STMT_ATTR_UPDATE_MAX_LENGTH, &flag)启用它。请参见25.2.7.3节,“mysql_stmt_attr_set()”

返回值

如果成功完成了对结果的缓冲处理,返回0。如果出现错误,返回非0值。

错误

·         CR_COMMANDS_OUT_OF_SYNC

以不恰当的顺序执行了命令。

·         CR_OUT_OF_MEMORY

内存溢出。

·         CR_SERVER_GONE_ERROR

MySQL服务器不可用。

·         CR_SERVER_LOST

在查询过程中,与服务器的连接丢失。

·         CR_UNKNOWN_ERROR

出现未知错误。

25.2.8. C API预处理语句方面的问题

下面列出了一些目前已知的与预处理语句有关的问题:

·         TIMETIMESTAMPDATETIME不支持秒部分,例如来自DATE_FORMAT()的秒部分

·         将整数转换为字符串时,在某些情况下,当MySQL不打印前导0时,可与预处理语句一起使用ZEROFILL。例如,与MIN(number-with-zerofill)一起。

·         将浮点数转换为客户端中的字符串时,被转换值最右侧的位可能会与原始值的有所不同。

·         预处理语句不使用查询高速缓冲,即使当查询不含任何占位符时也同样。。请参见5.13.1节,“查询高速缓冲如何工作”

25.2.9. 多查询执行的C API处理

MySQL 5.1支持在单个查询字符串中指定的多语句的执行。要想与给定的连接一起使用该功能,打开连接时,必须将标志参数中的CLIENT_MULTI_STATEMENTS选项指定给mysql_real_connect()也可以通过调用mysql_set_server_option(MYSQL_OPTION_MULTI_STATEMENTS_ON),为已有的连接设置它。

在默认情况下,mysql_query()mysql_real_query()仅返回第1个查询的状态,并能使用mysql_more_results()mysql_next_result()对后续查询的状态进行处理。

/* Connect to server with option CLIENT_MULTI_STATEMENTS */
mysql_real_connect(..., CLIENT_MULTI_STATEMENTS);
 
/* Now execute multiple queries */
mysql_query(mysql,"DROP TABLE IF EXISTS test_table;\
                   CREATE TABLE test_table(id INT);\
                   INSERT INTO test_table VALUES(10);\
                   UPDATE test_table SET id=20 WHERE id=10;\
                   SELECT * FROM test_table;\
                   DROP TABLE test_table");
do
{
  /* Process all results */
  ...
  printf("total affected rows: %lld", mysql_affected_rows(mysql));
  ...
  if (!(result= mysql_store_result(mysql)))
  {
     printf(stderr, "Got fatal error processing query\n");
     exit(1);
  }
  process_result_set(result); /* client function */
  mysql_free_result(result);
} while (!mysql_next_result(mysql));

多语句功能可与mysql_query()mysql_real_query()一起使用。它不能与预处理语句接口一起使用。按照定义,预处理语句仅能与包含单个语句的字符串一起使用。

25.2.10. 日期和时间值的C API处理

二进制协议允许你使用MYSQL_TIME结构发送和接受日期和时间值(DATETIMEDATETIMETIMESTAMP)。25.2.5节,“C API预处理语句的数据类型”中,介绍了该结构的成员。

要想发送临时数据值,可使用mysql_stmt_prepare()创建预处理语句。然后,在调用mysql_stmt_execute()执行语句之前,可采用下述步骤设置每个临时参数:

1.    在与数据值相关的MYSQL_BIND结构中,将buffer_type成员设置为相应的类型,该类型指明了发送的临时值类型。对于DATETIMEDATETIMETIMESTAMP值,buffer_type分别设置为MYSQL_TYPE_DATEMYSQL_TYPE_TIMEMYSQL_TYPE_DATETIMEMYSQL_TYPE_TIMESTAMP

2.    MYSQL_BIND结构的缓冲成员设置为用于传递临时值的MYSQL_TIME结构的地址。

3.    填充MYSQL_TIME结构的成员,使之与打算传递的临时支的类型相符。

使用mysql_stmt_bind_param()将参数数据绑定到语句。然后可调用mysql_stmt_execute()

要想检索临时值,可采用类似的步骤,但应将buffer_type成员设置为打算接受的值的类型,并将缓冲成员设为应将返回值置于其中的MYSQL_TIME结构的地址。调用mysql_stmt_execute()之后,并在获取结果之前,使用mysql_bind_results()将缓冲绑定到语句上。

下面给出了一个插入DATETIMETIMESTAMP数据的简单示例。假定mysql变量具有有效的连接句柄。

  MYSQL_TIME  ts;
  MYSQL_BIND  bind[3];
  MYSQL_STMT  *stmt;

  strmov(query, "INSERT INTO test_table(date_field, time_field,
                                        timestamp_field) VALUES(?,?,?");

  stmt = mysql_stmt_init(mysql);
  if (!stmt)
  {
    fprintf(stderr, " mysql_stmt_init(), out of memory\n");
    exit(0);
  }
  if (mysql_stmt_prepare(mysql, query, strlen(query)))
  {
    fprintf(stderr, "\n mysql_stmt_prepare(), INSERT failed");
    fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
    exit(0);
  }

  /* set up input buffers for all 3 parameters */
  bind[0].buffer_type= MYSQL_TYPE_DATE;
  bind[0].buffer= (char *)&ts;
  bind[0].is_null= 0;
  bind[0].length= 0;
  ...
  bind[1]= bind[2]= bind[0];
  ...

  mysql_stmt_bind_param(stmt, bind);

  /* supply the data to be sent in the ts structure */
  ts.year= 2002;
  ts.month= 02;
  ts.day= 03;

  ts.hour= 10;
  ts.minute= 45;
  ts.second= 20;

  mysql_stmt_execute(stmt);
  ..

25.2.11. C API线程函数介绍

当你打算创建线程客户端时,需要使用下述函数。请参见25.2.15节,“如何生成线程式客户端”

25.2.11.1. my_init()

void my_init(void)

描述

调用任何MySQL函数之前,需要在程序中调用该函数。它将初始化MySQL所需的某些全局变量。如果你正在使用线程安全客户端库,它还能为该线程调用mysql_thread_init()

通过mysql_init()mysql_library_init()mysql_server_init()mysql_connect(),可自动调用该函数。

返回值

无。

25.2.11.2. mysql_thread_init()

my_bool mysql_thread_init(void)

描述

对于每个创建的线程,需要调用该函数来初始化与线程相关的变量。

它可由my_init()mysql_connect()自动调用。

返回值

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

25.2.11.3. mysql_thread_end()

void mysql_thread_end(void)

描述

调用pthread_exit()来释放mysql_thread_init()分配的内存之前,需要调用该函数。

注意,该函数不会被客户端库自动调用。必须明确调用它以避免内存泄漏。

返回值

无。

25.2.11.4. mysql_thread_safe()

unsigned int mysql_thread_safe(void)

描述

该函数指明了客户端是否编译为线程安全的。

返回值

如果客户端是线程安全的,返回1,否则返回0

25.2.12. C API嵌入式服务器函数介绍

如果希望允许应用程序链接到嵌入式MySQL服务器库,必须使用mysql_server_init()mysql_server_end()函数。请参见25.1节,“libmysqld,嵌入式MySQL服务器库”

但是,要想提供改进的内存管理,即使是对与“-lmysqlclient”而不是与“-lmysqld”链接的程序,也应包含启用和结束库使用的调用。mysql_library_init()mysql_library_end()函数可用于该目的。它们实际上是使其等效于mysql_server_init()mysql_server_end()#define符号,但它们的名称更清楚地指明,无论应用程序使用的是libmysqlclientlibmysqld,开始使用或结束MySQL C API库的使用时,应调用它们。关于更多信息,请参见25.2.2节,“C API函数概述”

25.2.12.1. mysql_server_init()

int mysql_server_init(int argc, char **argv, char **groups)

描述

调用任何其他MySQL函数之前,必须在使用嵌入式服务器的程序中调用该函数。它将启动服务器,并初始化服务器使用的任何子系统(mysysInnoDB等)。如果未调用该函数,对mysql_init()的下一次调用将执行mysql_server_init()。如果你正在使用与MySQL一起提供的DBUG软件包,应在调用了my_init()之后调用它。

对于main()的参量,argcargv是类似的参量。argv的第1个元素将被忽略(典型情况下,它包含程序名)。为了方便起见,如果没有针对服务器的命令行参量,argc可以是0mysql_server_init()将复制参量,以便能够在调用之后安全地摧毁argvgroups

如果打算连接到外部服务器而不启动嵌入式服务器,应为argc指定负值。

groups”中以Null终结的字符串列表选择了选项文件中的活动“groups”。请参见4.3.2节,“使用选项文件”。为了方便起见,groups可以是NULL,在该情况下,[server][embedded]组是活动的。

示例:

#include 
#include 
 
static char *server_args[] = {
  "this_program",       /* this string is not used */
  "--datadir=.",
  "--key_buffer_size=32M"
};
static char *server_groups[] = {
  "embedded",
  "server",
  "this_program_SERVER",
  (char *)NULL
};
 
int main(void) {
  if (mysql_server_init(sizeof(server_args) / sizeof(char *),
                        server_args, server_groups))
    exit(1);
 
  /* Use any MySQL API functions here */
 
  mysql_server_end();
 
  return EXIT_SUCCESS;
}

返回值

如果OK,返回0。如果出现错误,返回1

25.2.12.2. mysql_server_end()

void mysql_server_end(void)

描述

在所有其他MySQL函数后,在程序中必须调用该函数一次。它将关闭嵌入式服务器。

返回值

无。

25.2.13. 使用C API时的常见问题

25.2.13.1. 为什么在mysql_query()返回成功后,mysql_store_result()有时会返回NULL

成功调用mysql_query()后,mysql_store_result()能够返回NULL。出现该情况时,表明出现了下述条件之一:

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

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

·         查询未返回数据(例如,它是INSERTUPDATEDELETE)。

通过调用mysql_field_count()始终能检查语句是否应生成非空结果。如果mysql_field_count()返回0,结果为空,而且上一个查询是未返回值的语句(例如INSERTDELETE)。如果mysql_field_count()返回非0值,语句应生成非空结果。关于这方面的示例,请参见mysql_field_count()函数介绍。

通过调用mysql_error()mysql_errno()可测试是否出现了错误。

25.2.13.2. What Results You Can Get from a Query

除了查询返回的结果集外,还能获取下述信息:

·         执行INSERTUPDATEDELETE时,mysql_affected_rows()返回上次查询影响的行数。

对于快速在创建,请使用TRUNCATE TABLE

·         mysql_num_rows()返回结果集中的行数。使用mysql_store_result(),一旦mysql_store_result()返回,就能调用mysql_num_rows()。使用mysql_use_result(),仅当用mysql_fetch_row()获取了所有行后,才能调用mysql_num_rows()

·         mysql_insert_id()返回上次查询生成的ID,该查询使用AUTO_INCREMENT索引将行插入到表内。请参见25.2.3.36节,“mysql_insert_id()”

·         某些查询(LOAD DATA INFILE ...INSERT INTO ... SELECT ...UPDATE)将返回额外信息。结果由mysql_info()返回。关于它返回的字符串格式,请参见关于mysql_info()的介绍。如果没有额外信息,mysql_info()将返回NULL指针。

25.2.13.3. 如何获得上次插入行的唯一ID

如果将记录插入包含AUTO_INCREMENT列的表中,通过调用mysql_insert_id()函数,可获取保存在该列中的值。

通过执行下述代码,可从C应用程序检查某一值是否保存在AUTO_INCREMENT列中(假定该语句已成功执行)。它能确定查询是否是具有AUTO_INCREMENT索引的INSERT

if ((result = mysql_store_result(&mysql)) == 0 &&
    mysql_field_count(&mysql) == 0 &&
    mysql_insert_id(&mysql) != 0)
{
    used_id = mysql_insert_id(&mysql);
}

关于更多信息,请参见25.2.3.36节,“mysql_insert_id()”

生成新的AUTO_INCREMENT值时,也能与mysql_query()一起通过执行SELECT LAST_INSERT_ID()语句获得它,并从该语句返回的结果集检索该值。

对于LAST_INSERT_ID(),最近生成的ID是在服务器上按连接维护的。它不会被另一个客户端改变。即使用non-magic值(即非Null0值)更新了另一个AUTO_INCREMENT列,也不会更改它。

如果打算使用从某一表生成的ID,并将其插入到第2个表中,可使用如下所示的SQL语句:

INSERT INTO foo (auto,text)
    VALUES(NULL,'text');              # generate ID by inserting NULL
INSERT INTO foo2 (id,text)
    VALUES(LAST_INSERT_ID(),'text');  # use ID in second table

注意,mysql_insert_id()返回保存在AUTO_INCREMENT列中的值,无论该值是因存储NULL0而自动生成的,或是明确指定的,均如此。LAST_INSERT_ID()仅返回自动生成的AUTO_INCREMENT值。如果你保存了除NULL0之外的确切值,不会影响LAST_INSERT_ID()返回的值。

25.2.13.4. 与C API有关的问题

C API链接时,在某些系统上可能出现下述错误:
gcc -g -o client test.o -L/usr/local/lib/mysql -lmysqlclient -lsocket -lnsl
 
Undefined        first referenced
 symbol          in file
floor            /usr/local/lib/mysql/libmysqlclient.a(password.o)
ld: fatal: Symbol referencing errors. No output written to client

如果在你的系统上出现了该情况,必须在编译/链接行的末尾增加“-lm”,通过该方式包含数学库。

25.2.14. 创建客户端程序

如果你编译了自己编写的MySQL客户端,或编译了从第三方获取的MySQL客户端,必须在链接命令中使用“-lmysqlclient -lz”选项链接它们。你或许还应指定“-L”选项,通知链接程序到哪里找到库。例如,如果将库安装到了/usr/local/mysql/lib,可在链接命令中使用sr/local/mysql/lib -lmysqlclient –lz

对于使用MySQL头文件的客户端,编译它们时还须指定“-I”选项(例如-I/usr/local/mysql/include),以便编译器能找到头文件。

为了使在Unix平台上编译MySQL程序变得简单,提供了mysql_config脚本。请参见25.9.2节,“mysql_config:获取编译客户端的编译选项”

你也可以使用它来编译MySQL客户端,如下所述:

CFG=/usr/local/mysql/bin/mysql_config
sh -c "gcc -o progname `$CFG --cflags` progname.c `$CFG --libs`"

需要使用“sh –c”,使得shell不将mysql_config的输出当作1个词对待。

25.2.15. 如何生成线程式客户端

客户端库总是线程安全的。最大的问题在于从套接字读取的net.c中的子程序并不是中断安全的。或许你可能希望用自己的告警中断对服务器的长时间读取,以此来解决问题。如果为SIGPIPE中断安装了中断处理程序,套接字处理功能应是线程安全的。

为了避免连接中断时放弃程序,MySQL将在首次调用mysql_server_init()mysql_init()mysql_connect()时屏蔽SIGPIPE。如果你打算使用自己的SIGPIPE处理程序,首先应调用mysql_server_init(),然后安装你的处理程序,

在较旧的发布在我方网站上()的二进制版本中,未用线程安全的选项对客户端库进行正常编译(默认情况下,编译的Windows二进制版本是线程安全的)。较新的二进制分发版应是正常的和线程安全的客户端库。

为了获得能从其他线程中断客户端的线程式客户端,并在与MySQL服务器通信时设置超时,应使用“-lmysys”、“-lmystrings”-ldbug”库,以及服务器使用的net_serv.o代码。

如果你不需要使用中断或超时,可编译线程安全客户端库(mysqlclient_r)并使用它。。请参见25.2节,“MySQL C API”。在该情况下,不必担心net_serv.o对象文件或其他MySQL库。

使用线程式客户端并打算使用超时或中断时,可更好地利用thr_alarm.c文件中的子程序。如果你正在使用来自mysys库的子程序,唯一需要记住的事是首先调用my_init()!请参见25.2.11节,“C API线程函数介绍”

对于除mysql_real_connect()外的所有函数,在默认情况下它们均是线程安全的。在下面的说明中,介绍了编译线程安全客户端库的方法,以及以线程安全方式使用它的方法。(下面关于mysql_real_connect()的说明实际上也适用于mysql_connect(),但由于mysql_connect()已不再被重视,总应尽量使用mysql_real_connect())。

要想使mysql_real_connect()成为线程安全的,必须用下述命令再次编译客户端库:

shell> ./configure --enable-thread-safe-client

它创建了线程安全客户端库libmysqlclient_r。(假定你的操作系统有线程安全的gethostbyname_r()函数)。按照连接,该库是线程安全的。可遵循下述警告,使两个线程共享相同的连接:

·         在相同的连接上,两个线程不能同时将查询发送到MySQL服务器。尤其是,必须确保在mysql_query()mysql_store_result()之间,没有使用相同连接的其他线程。

·         很多线程均能访问由mysql_store_result()检索的不同结果集。

·         如果使用了mysql_use_result,务必确保无其他线程正在使用相同的连接,直至关闭了结果集为止。然而,对于线程式客户端,最好是共享相同的连接以使用mysql_store_result()

·         如果打算在相同的连接上使用多个线程,必须在mysql_query()mysql_store_result()调用组合上拥有互斥锁。一旦mysql_store_result()准备就绪,可释放锁定,其他线程可在相同的连接上执行查询。

·         如果使用POSIX线程进行编程,可使用pthread_mutex_lock()pthread_mutex_unlock()来建立并释放互斥锁。

如果你有1个调用MySQL函数的线程,而该函数未创建与MySQL数据库的连接,就需了解下述事宜:

调用mysql_init()mysql_connect()时,MySQL会为调试库使用的线程创建与线程相关的变量(尤其)。

在线程调用mysql_init()mysql_connect()之前,如果调用了MySQL函数,该线程将没有所需的线程类变量,而且你很可能或早或晚结束于内核转储。

要想使这些操作平稳工作,需要采取下述措施:

1.    如果程序在调用mysql_real_connect()之前需要调用任何其他MySQL函数,请在启动程序时调用my_init()

2.    调用任何MySQL函数之前,在线程处理程序中调用mysql_thread_init()

3.    在线程中,调用pthread_exit()之前请调用mysql_thread_end()。这样,就能释放MySQL线程类变量使用的内存。

将客户端链接到libmysqlclient_r时,如果存在未定义的符号,可能会出错。在大多数情况下,其原因在于,未将线程库包含在link/compile行上。

25.3. MySQL PHP API

PHP是一种服务器端、HTML嵌入式脚本处理语言,可使用该语言创建动态网页。它可用于大多数操作系统和Web服务器,也能访问大多数常见数据库,包括MySQLPHP可以作为单独程序运行,也能编译为模块,用于Apache Web服务器。

PHP实际上提供了两种不同的MySQL API扩展:

·         mysql:适用于PHP版本45,该扩展用于MySQL 4.1之前的MySQL版本。该扩展不支持MySQL 5.1中采用的、改进的鉴定协议,也不支持与预处理语句或多语句。如果打算与MySQL 5.1一起使用该扩展,应配置MySQL服务器,以使用“--old-passwords”选项(请参见A.2.3节,“客户端不支持鉴定协议”)。在PHP网站的文档中记录了该该扩展

·         mysqli是“MySQL, Improved”的缩写,该扩展仅适用于PHP 5。它能用于MySQL 4.1.1和更高版本。该扩展完全支持MySQL 5.1中采用的鉴定协议,也支持预处理语句和多语句API。此外,该扩展还提供了先进的、面向对象的编程接口。在上,可找到关于mysqli扩展的文档。在处,给出了一篇有用的文章。

PHP分发版和文档均能从获得。

25.3.1. 使用MySQL和PHP的常见问题

·         错误:超出了最大执行时间,这是一种PHP限制,如果需要,进入文件php.ini,并设置最大执行时间(开始为30秒)。此外,还可以将每脚本允许使用的RAM增加一倍,8MB变为16MB,这也是个不错的主意。

·         致命错误:在中调用了不支持或未定义的mysql_connect()函数,这意味着,你的PHP版本不支持MySQL。你可以编译动态MySQL模块并将其加载到PHP,或使用内置的MySQL支持重新编译PHP。在PHP手册中,详细介绍了该进程。

·         错误:对'uncompress'的未定义引用,这意味着所编译的客户端库支持压缩客户端/服务器协议。更正方法是,用“-lmysqlclient”进行链接时,在最后添加“-lz”

·         错误:客户端不支持鉴定协议,与MySQL 4.1.1和更高版本一起使用较旧的mysql扩展时常会遇到该问题。可能的解决方案是:降级到MySQL 4.0,转向PHP 5和较新的mysqli扩展,或用“--old-passwords”配置MySQL服务器(更多信息,请参见A.2.3节,“客户端不支持鉴定协议”)。

25.4. MySQL Perl API

Perl DBI模块为数据库访问提供了一个通用接口。能够编写无需更改就能与不同的数据库引擎一起工作的DBI脚本。要想使用DBI,必须安装DBI模块,并为打算访问的每种服务器安装数据库驱动程序(DBD)模块。对于MySQL,该驱动程序是DBD::mysql模块。

Perl DBI是推荐的Perl接口。它取代了旧的名为mysqlperl的接口,mysqlperl已过时。

关于Perl DBI支持的安装说明,请参见2.13节,“Perl安装注意事项”

DBI信息能够在命令行上提供,也能以在线方式提供,或采用印刷形式:

·         一旦安装了DBIDBD::mysql模块,可使用perldoc 命令在命令行上获取关于它们的信息:

·                shell> perldoc DBI
·                shell> perldoc DBI::FAQ
·                shell> perldoc DBD::mysql

也可以使用pod2manpod2html将这类信息转换为其他格式。

·         关于Perl DBI的在线信息,请访问DBI网站,。该站点还提供了1个一般性DBI邮件列表。MySQL AB提供了1个专门针对DBD::mysql 的邮件列表,请参见

·         至于印刷版信息,官方的DBI书籍是编程Perl DBIAlligator DescartesTim BunceO'Reilly & Associates, 2000)。关于该书的信息,请访问DBI网站

关于与MySQL一起使用DBI的专门信息,请参见针对WebMySQLPerlPaul DuBois, New Riders, 2001)。该书的网站是

25.5. MySQL C++ API

MySQL++是用于C++MySQL APIWarren Young负责该项目。要想了解更多信息,请访问

25.5.1. Borland C++

可以使用Borland C++ 5.02编译MySQL Windows源码(Windows源码仅包括用于Microsoft VC++的项目,对于Borland C++,你将不得不自己编制项目文件)。

使用Borland C++时的1个已知问题是,它采用了不同于VC++的结构对齐方式。这意味着,如果你打算与Borland C++一起使用默认的libmysql.dll库(它是使用VC++编译的),将会遇到问题。为了避免该问题,仅应调用将Null作为参量的mysql_init(),而不是预先分配MYSQL结构。

25.6. MySQL Python API

MySQLdbPython提供了MySQL支持,它符合Python DB API版本2.0的要求,可在上找到它。

25.7. MySQL Tcl API

MySQLtcl是一种简单的API,用于从Tcl编程语言访问MySQL数据库服务器。可在上找到它。

25.8. MySQL Eiffel Wrapper

Eiffel MySQL是一种与MySQL数据库服务器的接口,它采用的是Eiffel编程语言,由Michael Ravits编写。可在上找到它。

25.9. MySQL程序开发实用工具

在本节中,介绍了开发MySQL程序时可能会有用的一些实用工具。

·         msql2mysql

1shell脚本,用于将mSQL程序转换为MySQL程序。它不能处理所有情况,但能为转换提供良好的开端。

·         mysql_config

1shell脚本,能生成编译MySQL程序时所需的选项值。

25.9.1. msql2mysql:转换mSQL程序以用于MySQL

最初,开发的MySQL C API很类似为mSQL数据库系统开发的API。正因为如此,通过更改C API函数的名称,通常能相对容易地转换mSQL程序,使之用于MySQL

msql2mysql实用工具用于将mSQL C API函数调用转换为其MySQL对等物。msql2mysql能够转换位于恰当位置输入文件,在执行具体转换之前复制原件。例如,可采用下述方式使用msql2mysql

shell> cp client-prog.c client-prog.c.orig
shell> msql2mysql client-prog.c
client-prog.c converted

然后,检查client-prog.c,并执行可能需要的后期转换修订。

msql2mysql使用replace实用工具来替换函数名。请参见8.14节,“replace:字符串替换实用工具”

25.9.2. mysql_config:获取编译客户端的编译选项

mysql_config提供了关于编译MySQL客户端以及将其连接到MySQL的有用信息。

mysql_config支持下述选项:

·         --cflags

编译器标志,用于查找包含文件,以及编译libmysqlclient库时所要使用的关键编译器标志和定义。

·         --include

编译器选项,用于查找MySQL包含文件(注意,正常情况下应使用“—cflags”而不是该选项)。

·         --libmysqld-libs, ---embedded

MySQL嵌入式服务器进行链接所需的库和选项。

·         --libs

MySQL客户端库进行链接所需的库和选项。

·         --libs_r

与线程安全MySQL客户端库进行链接所需的库和选项。

·         --port

默认的TCP/IP端口号,配置MySQL时定义。

·         --socket

默认的Unix套接字文件,配置MySQL时定义。

·         --version

版本号以及MySQL分发版的版本。

如果未使用任何选项调用了mysql_config,将显示它所支持的所有选项的列表,以及它们的值:

shell> mysql_config
Usage: /usr/local/mysql/bin/mysql_config [options]
Options:
  --cflags         [-I/usr/local/mysql/include/mysql -mcpu=pentiumpro]
  --include        [-I/usr/local/mysql/include/mysql]
  --libs           [-L/usr/local/mysql/lib/mysql -lmysqlclient -lz
                    -lcrypt -lnsl -lm -L/usr/lib -lssl -lcrypto]
  --libs_r         [-L/usr/local/mysql/lib/mysql -lmysqlclient_r
                    -lpthread -lz -lcrypt -lnsl -lm -lpthread]
  --socket         [/tmp/mysql.sock]
  --port           [3306]
  --version        [4.0.16]
  --libmysqld-libs [-L/usr/local/mysql/lib/mysql -lmysqld -lpthread -lz
                    -lcrypt -lnsl -lm -lpthread -lrt]

可以在命令行上使用mysql_config,并包含针对特定选项的值。例如,要想编译MySQL客户端程序,可使用mysql_config,如下例所示:

shell> CFG=/usr/local/mysql/bin/mysql_config
shell> sh -c "gcc -o progname `$CFG --cflags` progname.c `$CFG --libs`"

以这种方式使用mysql_config时,务必在字符(`)内调用它。这样,就能通知shell执行它,并将其输出代入到环境命令中。


dev.mysql.com。 原始参考手册为英文版,与英文版参考手册相比,本翻译版可能不是最新的。

阅读(1099) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~