第25章:API和库 / 25.2. MySQL C API / 25.2.7. C API预处理语句函数描述
25.2.7.1. mysql_stmt_affected_rows()
25.2.7.2. mysql_stmt_attr_get()
25.2.7.3. mysql_stmt_attr_set()
25.2.7.4. mysql_stmt_bind_param()
25.2.7.5. mysql_stmt_bind_result()
25.2.7.6. mysql_stmt_close()
25.2.7.7. mysql_stmt_data_seek()
25.2.7.8. mysql_stmt_errno()
25.2.7.9. mysql_stmt_error()
25.2.7.10. mysql_stmt_execute()
25.2.7.11. mysql_stmt_fetch()
25.2.7.12. mysql_stmt_fetch_column()
25.2.7.13. mysql_stmt_field_count()
25.2.7.14. mysql_stmt_free_result()
25.2.7.15. mysql_stmt_init()
25.2.7.16. mysql_stmt_insert_id()
25.2.7.17. mysql_stmt_num_rows()
25.2.7.18. mysql_stmt_param_count()
25.2.7.19. mysql_stmt_param_metadata()
25.2.7.20. mysql_stmt_prepare()
25.2.7.21. mysql_stmt_reset()
25.2.7.22. mysql_stmt_result_metadata()
25.2.7.23. mysql_stmt_row_seek()
25.2.7.24. mysql_stmt_row_tell()
25.2.7.25. mysql_stmt_send_long_data()
25.2.7.26. mysql_stmt_sqlstate()
25.2.7.27. mysql_stmt_store_result()

为了准备和执行查询,请使用下述部分详细介绍的函数。

注意,与MYSQL_STMT结构一起使用的所有函数均以前缀mysql_stmt_开始。

要想创建MYSQL_STMT句柄,请使用mysql_stmt_init()函数。

25.2.7.1. mysql_stmt_affected_rows()

my_ulonglong mysql_stmt_affected_rows(MYSQL_STMT *stmt)

描述

返回上次执行语句更改、删除或插入的总行数。对于UPDATEDELETEINSERT语句,可在mysql_stmt_execute()之后立刻调用它们。对于SELECT语句,mysql_stmt_affected_rows()的工作方式类似于mysql_num_rows()

返回值

大于0的整数指明了受影响或检索的行数。对于UPDATE语句,“0”表明未更新任何记录,在查询中没有与WHERE子句匹配的行,或尚未执行任何查询。-1”表明返回了错误,或对SELECT查询,在调用mysql_stmt_store_result()之前调用了mysql_stmt_affected_rows()。由于mysql_stmt_affected_rows()返回无符号值,可通过比较返回值和“(my_ulonglong)-1”(或等效的“(my_ulonglong)~0”,检查“-1”。

关于返回值的额外信息,请参见25.2.3.1节,“mysql_affected_rows()”

错误

无。

示例:

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

25.2.7.2. mysql_stmt_attr_get()

int mysql_stmt_attr_get(MYSQL_STMT *stmt, enum enum_stmt_attr_type option, void *arg)

描述

可用于获得语句属性的当前值。

option”参量是希望获取的选项,“arg”应指向包含选项值的变量。如果option”是整数,那么“arg”应指向整数的值。

关于选项和选项类型的清单,请参见25.2.7.3节,“mysql_stmt_attr_set()”

返回值

如果OK,返回0如果选项未知,返回非0值。

错误

无。

25.2.7.3. mysql_stmt_attr_set()

int mysql_stmt_attr_set(MYSQL_STMT *stmt, enum enum_stmt_attr_type option, const void *arg)

描述

可用于影响预处理语句的行为。可多次调用该函数来设置多个选项。

option”参量是希望设置的选项,arg”参量是选项的值。如果option”是整数,那么“arg”应指向整数的值。

可能的选项值:

选项

参量类型

功能

STMT_ATTR_UPDATE_MAX_LENGTH

my_bool *

如果设为1:更新mysql_stmt_store_result()中的元数据MYSQL_FIELD->max_length

STMT_ATTR_CURSOR_TYPE

unsigned long *

调用mysql_stmt_execute()时,语句将打开的光标类型。*arg可以是CURSOR_TYPE_NO_CURSOR(默认值)或CURSOR_TYPE_READ_ONLY

STMT_ATTR_PREFETCH_ROWS

unsigned long *

使用光标时,一次从服务器获取的行数。*arg的范围从1unsigned long的最大值。默认值为1

如果与CURSOR_TYPE_READ_ONLY一起使用了STMT_ATTR_CURSOR_TYPE选项,当调用了mysql_stmt_execute()时,将为语句打开光标。如果存在由前一个mysql_stmt_execute()调用打开的光标,在打开新的光标前,将关闭该光标。此外,为再执行而准备语句之前,mysql_stmt_reset()还将关闭任何打开的光标。mysql_stmt_free_result()将关闭任何打开的光标。

如果为预处理语句打开了光标,没必要调用mysql_stmt_store_result(),这是因为,该函数会导致在客户端一侧对结果集进行缓冲处理。

MySQL 5.0.2中增加了STMT_ATTR_CURSOR_TYPE选项。在MySQL 5.0.6中,增加了STMT_ATTR_PREFETCH_ROWS选项。

返回值

如果OK,返回0如果选项未知,返回非0值。

错误

无。

示例:

在下述示例中,为预处理语句打开了1个光标,并将每次获取的行数设为5

MYSQL_STMT *stmt;
int rc;
unsigned long type;
unsigned long prefetch_rows = 5;
 
stmt = mysql_stmt_init(mysql);
type = (unsigned long) CURSOR_TYPE_READ_ONLY;
rc = mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*) &type);
/* ... check return value ... */
rc = mysql_stmt_attr_set(stmt, STMT_ATTR_PREFETCH_ROWS,
                                        (void*) &prefetch_rows);
/* ... check return value ... */

25.2.7.4. mysql_stmt_bind_param()

my_bool mysql_stmt_bind_param(MYSQL_STMT *stmt, MYSQL_BIND *bind)

描述

mysql_stmt_bind_param()用于SQL语句中的参数标记符绑定数据,以传递给mysql_stmt_prepare()。它使用MYSQL_BIND结构来提供数据。bind”MYSQL_BIND结构的某一数组的地址。按照客户端库的预期,对于查询中出现的每个“?”参数标记符,数组中均包含1个元素。

假定你准备了下述语句:

INSERT INTO mytbl VALUES(?,?,?)

绑定参数时,MYSQL_BIND结构的数组包含3个元素,并能声明如下:

MYSQL_BIND bind[3];

25.2.5节,“C API预处理语句的数据类型”中,介绍了应设置的每个MYSQL_BIND元素的成员。

返回值

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

错误

·         CR_INVALID_BUFFER_USE

指明“bind”(绑定)是否将提供程序块中的长数据,以及缓冲类型是否为非字符串或二进制类型。

·         CR_UNSUPPORTED_PARAM_TYPE

不支持该转换。或许buffer_type值是非法的,或不是所支持的类型之一。

·         CR_OUT_OF_MEMORY

内存溢出。

·         CR_UNKNOWN_ERROR

出现未知错误。

示例:

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

25.2.7.5. mysql_stmt_bind_result()

my_bool mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)

描述

mysql_stmt_bind_result()用于将结果集中的列与数据缓冲和长度缓冲关联(绑定)起来。当调用mysql_stmt_fetch()以获取数据时,MySQL客户端/服务器协议会将绑定列的数据置于指定的缓冲区内。

调用mysql_stmt_fetch()之前,必须将所有列绑定到缓冲。“bind”MYSQL_BIND结构某一数组的地址。按照客户端库的预期,对于结果集中的每一列,数组应包含相应的元素。如果未将列绑定到MYSQL_BIND结构,mysql_stmt_fetch()将简单地忽略数据获取操作。缓冲区应足够大,足以容纳数据值,这是因为协议不返回成块的数据值。

可以在任何时候绑定或再绑定列,即使已部分检索了结果集后也同样。新的绑定将在下一次调用mysql_stmt_fetch()时起作用。假定某一应用程序绑定了结果集中的列,并调用了mysql_stmt_fetch()。客户端/服务器协议将返回绑定缓冲区中的数据。接下来,假定应用程序将多个列绑定到不同的缓冲。该协议不会将数据置于新绑定的缓冲区,直至下次调用mysql_stmt_fetch()为止。

要想绑定列,应用程序将调用mysql_stmt_bind_result(),并传递类型、地址、以及长度缓冲的地址。在25.2.5节,“C API预处理语句的数据类型”中,介绍了应设置的各MYSQL_BIND元素的成员。

返回值

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

错误

·         CR_UNSUPPORTED_PARAM_TYPE

不支持该转换。或许buffer_type值是非法的,或不是所支持的类型之一。

·         CR_OUT_OF_MEMORY

内存溢出。

·         CR_UNKNOWN_ERROR

出现未知错误。

示例:

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

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

出现未知错误。