27.7.10.11 mysql_stmt_fetch()
int mysql_stmt_fetch(MYSQL_STMT *stmt)
Description
mysql_stmt_fetch()返回结果集中的下一行。仅当结果集存在时才可以调用它。也就是说,在调用mysql_stmt_execute()以生成诸如结果集之类的SELECT之类的语句之后。
mysql_stmt_fetch()使用mysql_stmt_bind_result()绑定的缓冲区返回行数据。它为当前行集中的所有列返回那些缓冲区中的数据,并将长度返回到length
指针。应用程序在调用mysql_stmt_fetch()之前必须将所有列绑定。
mysql_stmt_fetch()通常在循环内发生,以确保提取所有结果集行。例如:
int status;
while (1)
{
status = mysql_stmt_fetch(stmt);
if (status == 1 || status == MYSQL_NO_DATA)
break;
/* handle current row here */
}
/* if desired, handle status == 1 case and display error here */
默认情况下,一次从服务器无缓冲地获取结果集。要在 Client 端上缓冲整个结果集,请在绑定数据缓冲区之后并在调用mysql_stmt_fetch()之前调用mysql_stmt_store_result()。
如果获取的数据值为NULL
值,则对应的MYSQL_BIND
结构的*is_null
值包含 TRUE(1)。否则,将根据应用程序指定的缓冲区类型在*buffer
和*length
元素中返回数据及其长度。每种数字和时间类型都有固定的长度,如下 table 所示。字符串类型的长度取决于实际数据值的长度,如data_length
所示。
Type | 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 |
在某些情况下,您可能需要先确定列值的长度,然后再使用mysql_stmt_fetch()进行获取。例如,该值可能是一个长字符串或BLOB值,您想为其分配多少空间。为此,请使用以下策略之一:
-
在调用mysql_stmt_fetch()检索单个行之前,请将
STMT_ATTR_UPDATE_MAX_LENGTH
传递给mysql_stmt_attr_set(),然后调用mysql_stmt_store_result()在 Client 端缓存整个结果。设置STMT_ATTR_UPDATE_MAX_LENGTH
属性会使列值的最大长度由mysql_stmt_result_metadata()返回的结果集元数据的max_length
成员指示。 -
调用mysql_stmt_fetch(),该列的长度为零,缓冲区的长度为零,并且指针可以存储实际长度。然后使用mysql_stmt_fetch_column()的实际长度。
real_length= 0;
bind[0].buffer= 0;
bind[0].buffer_length= 0;
bind[0].length= &real_length
mysql_stmt_bind_result(stmt, bind);
mysql_stmt_fetch(stmt);
if (real_length > 0)
{
data= malloc(real_length);
bind[0].buffer= data;
bind[0].buffer_length= real_length;
mysql_stmt_fetch_column(stmt, bind, 0, 0);
}
Return Values
Return Value | Description |
---|---|
0 | 成功,数据已被提取到应用程序数据缓冲区。 |
1 | 错误发生。可以通过调用mysql_stmt_errno()和mysql_stmt_error()获得错误代码和消息。 |
MYSQL_NO_DATA | 成功,没有更多数据 |
MYSQL_DATA_TRUNCATED | 发生数据截断 |
启用截断报告后,将返回MYSQL_DATA_TRUNCATED
。若要确定返回该值时哪些列值被截断,请检查用于获取值的MYSQL_BIND
结构的error
成员。截断报告默认情况下处于启用状态,但可以通过使用MYSQL_REPORT_DATA_TRUNCATION
选项调用mysql_options()来控制。
Errors
命令执行 Sequences 不正确。
尽管mysql_stmt_fetch()会产生此错误,但如果调用mysql_stmt_fetch()的次数不足以读取整个结果集(即,有足够的次数返回MYSQL_NO_DATA
),则* C * API 后续调用更有可能发生。
记不清。
MySQL 服务器已经消失了。
在查询期间与服务器的连接已丢失。
出现未知错误。
缓冲区类型为MYSQL_TYPE_DATE
,MYSQL_TYPE_TIME
,MYSQL_TYPE_DATETIME
或MYSQL_TYPE_TIMESTAMP
,但数据类型不是DATE,TIME,DATETIME或TIMESTAMP。
- 所有其他不受支持的转换错误均从mysql_stmt_bind_result()返回。
Example
下面的示例演示如何使用mysql_stmt_result_metadata(),mysql_stmt_bind_result()和mysql_stmt_fetch()从 table 中获取数据。 (此示例希望检索第 27.7.10.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];
my_bool error[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];
bind[0].error= &error[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];
bind[1].error= &error[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];
bind[2].error= &error[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[3].error= &error[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 (optional step) */
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))
{
/* mysql_stmt_close() invalidates stmt, so call */
/* mysql_error(mysql) rather than mysql_stmt_error(stmt) */
fprintf(stderr, " failed while closing the statement\n");
fprintf(stderr, " %s\n", mysql_error(mysql));
exit(0);
}