使用 C api 解决 MYSQL 截断问题
Troubleshoot MYSQL truncation with C api
我在 MYSQL C API 中使用准备好的语句,但遇到截断问题。 mysql_stmt_fetch()
总是 returns MYSQL_DATA_TRUNCATED
我不明白为什么。有人可以告诉我为什么数据会被截断以帮助我解决此问题的原因吗?我能想到的唯一原因是我的缓冲区变量的类型不正确,但我认为它们是正确的类型。如果您有兴趣,我正在使用的代码如下。我还展示了我的 table 及其结构的副本,这是我直接从 MYSQL 客户端中的命令中获取的。
关于代码的一些注释:
我修改了它以打印出值,即使它 returns 截断了数据。当我这样做时,第一个字段似乎打印正确,但浮动字段和日期时间字段出现乱码。此外,它似乎读取了正确的行数。
大部分代码用于检查各种函数调用的错误。 None 的这些错误检查被触发 - 或者至少 none 的错误检查打印出您期望的消息。唯一的错误指示是 fetch 调用返回的 MYSQL_DATA_TRUNCATED
值。
描述尺寸 Table:
+------------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+----------+------+-----+---------+-------+
| nodeId | int(11) | NO | PRI | NULL | |
| recordtime | datetime | NO | PRI | NULL | |
| slevel | float | YES | | NULL | |
+------------+----------+------+-----+---------+-------+
当前测量内容Table:
+--------+---------------------+--------+
| nodeId | recordtime | slevel |
+--------+---------------------+--------+
| 1 | 2015-09-22 19:33:50 | 2 |
| 1 | 2015-09-24 21:10:20 | 2 |
| 2 | 2015-09-22 19:33:53 | 5 |
| 3 | 2015-09-22 19:33:55 | 2 |
| 3 | 2015-09-22 19:45:42 | 4 |
| 3 | 2015-09-24 21:12:12 | 2 |
| 3 | 2015-09-24 21:13:30 | 3.4 |
| 4 | 2015-09-22 19:33:57 | 7 |
| 4 | 2015-09-24 21:05:53 | 5 |
| 4 | 2015-09-24 21:07:27 | 3 |
| 4 | 2015-09-24 21:22:52 | 9.9 |
| 4 | 2015-09-24 21:35:53 | 5 |
| 6 | 2015-09-24 21:26:01 | 2.2 |
| 6 | 2015-09-24 21:28:15 | 5.4 |
+--------+---------------------+--------+
14 rows in set (0.00 sec)
我的代码:
static void select_rows (MYSQL_STMT *stmt){
char *stmt_str = "SELECT nodeId, recordtime, slevel FROM Measurements";
MYSQL_BIND param[3];
int my_int;
float my_float;
MYSQL_TIME my_datetime;
my_bool is_null[3];
if (mysql_stmt_prepare (stmt, stmt_str, strlen (stmt_str)) != 0){
print_stmt_error (stmt, "Could not prepare SELECT statement");
return;}
if (mysql_stmt_field_count (stmt) != 3){
print_stmt_error (stmt, "Unexpected column count from SELECT");
return;}
memset ((void *) param, 0, sizeof (param)); /* zero the structures */
/* set up INT parameter */
param[0].buffer_type = MYSQL_TYPE_LONG;
param[0].buffer = (void *) &my_int;
param[0].is_unsigned = 0;
param[0].is_null = &is_null[0];
/* set up FLOAT parameter */
param[1].buffer_type = MYSQL_TYPE_FLOAT;
param[1].buffer = (void *) &my_float;
param[1].buffer = (void *) &my_float;
param[1].is_null = &is_null[1];
/* set up DATETIME parameter */
param[2].buffer_type = MYSQL_TYPE_DATETIME;
param[2].buffer = (void *) &my_datetime;
param[2].is_null = &is_null[2];
if (mysql_stmt_bind_result (stmt, param) != 0){
print_stmt_error (stmt, "Could not bind parameters for SELECT");
return;}
if (mysql_stmt_execute (stmt) != 0){
print_stmt_error (stmt, "Could not execute SELECT");
return;}
if (mysql_stmt_store_result (stmt) != 0){
print_stmt_error (stmt, "Could not buffer result set");
return;}
else{
printf ("Number of rows retrieved: %lu\n",
(unsigned long) mysql_stmt_num_rows (stmt));}
int ii = mysql_stmt_fetch (stmt);
while (ii == 0 || ii==MYSQL_DATA_TRUNCATED) /* fetch each row */
{
/* display row values */
printf ("%d ", my_int);
printf ("%.2f ", my_float);
printf ("%04d-%02d-%02d %02d:%02d:%02d\n",
my_datetime.year,
my_datetime.month,
my_datetime.day,
my_datetime.hour,
my_datetime.minute,
my_datetime.second);
ii=mysql_stmt_fetch (stmt);
}
mysql_stmt_free_result (stmt); /* deallocate result set */
}
事实证明这是一个令人沮丧的简单错误。我的 MYSQL_BIND
结构的顺序不正确,mysql_stmt_bind_param()
没有返回错误来指示数据类型不匹配。您可以看到浮点数在我的数据库中的字段 3 中,但在我的 param[]
数组中的第二个字段中。切换 MYSQL_BIND
结构的顺序解决了我的问题。
我 post 这个解决方案而不是删除这个问题,因为在网上其他地方找不到关于 MYSQL 截断错误的信息,而其他人可能会犯这个微妙但简单的错误。
我在 MYSQL C API 中使用准备好的语句,但遇到截断问题。 mysql_stmt_fetch()
总是 returns MYSQL_DATA_TRUNCATED
我不明白为什么。有人可以告诉我为什么数据会被截断以帮助我解决此问题的原因吗?我能想到的唯一原因是我的缓冲区变量的类型不正确,但我认为它们是正确的类型。如果您有兴趣,我正在使用的代码如下。我还展示了我的 table 及其结构的副本,这是我直接从 MYSQL 客户端中的命令中获取的。
关于代码的一些注释:
我修改了它以打印出值,即使它 returns 截断了数据。当我这样做时,第一个字段似乎打印正确,但浮动字段和日期时间字段出现乱码。此外,它似乎读取了正确的行数。
大部分代码用于检查各种函数调用的错误。 None 的这些错误检查被触发 - 或者至少 none 的错误检查打印出您期望的消息。唯一的错误指示是 fetch 调用返回的 MYSQL_DATA_TRUNCATED
值。
描述尺寸 Table:
+------------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+----------+------+-----+---------+-------+
| nodeId | int(11) | NO | PRI | NULL | |
| recordtime | datetime | NO | PRI | NULL | |
| slevel | float | YES | | NULL | |
+------------+----------+------+-----+---------+-------+
当前测量内容Table:
+--------+---------------------+--------+
| nodeId | recordtime | slevel |
+--------+---------------------+--------+
| 1 | 2015-09-22 19:33:50 | 2 |
| 1 | 2015-09-24 21:10:20 | 2 |
| 2 | 2015-09-22 19:33:53 | 5 |
| 3 | 2015-09-22 19:33:55 | 2 |
| 3 | 2015-09-22 19:45:42 | 4 |
| 3 | 2015-09-24 21:12:12 | 2 |
| 3 | 2015-09-24 21:13:30 | 3.4 |
| 4 | 2015-09-22 19:33:57 | 7 |
| 4 | 2015-09-24 21:05:53 | 5 |
| 4 | 2015-09-24 21:07:27 | 3 |
| 4 | 2015-09-24 21:22:52 | 9.9 |
| 4 | 2015-09-24 21:35:53 | 5 |
| 6 | 2015-09-24 21:26:01 | 2.2 |
| 6 | 2015-09-24 21:28:15 | 5.4 |
+--------+---------------------+--------+
14 rows in set (0.00 sec)
我的代码:
static void select_rows (MYSQL_STMT *stmt){
char *stmt_str = "SELECT nodeId, recordtime, slevel FROM Measurements";
MYSQL_BIND param[3];
int my_int;
float my_float;
MYSQL_TIME my_datetime;
my_bool is_null[3];
if (mysql_stmt_prepare (stmt, stmt_str, strlen (stmt_str)) != 0){
print_stmt_error (stmt, "Could not prepare SELECT statement");
return;}
if (mysql_stmt_field_count (stmt) != 3){
print_stmt_error (stmt, "Unexpected column count from SELECT");
return;}
memset ((void *) param, 0, sizeof (param)); /* zero the structures */
/* set up INT parameter */
param[0].buffer_type = MYSQL_TYPE_LONG;
param[0].buffer = (void *) &my_int;
param[0].is_unsigned = 0;
param[0].is_null = &is_null[0];
/* set up FLOAT parameter */
param[1].buffer_type = MYSQL_TYPE_FLOAT;
param[1].buffer = (void *) &my_float;
param[1].buffer = (void *) &my_float;
param[1].is_null = &is_null[1];
/* set up DATETIME parameter */
param[2].buffer_type = MYSQL_TYPE_DATETIME;
param[2].buffer = (void *) &my_datetime;
param[2].is_null = &is_null[2];
if (mysql_stmt_bind_result (stmt, param) != 0){
print_stmt_error (stmt, "Could not bind parameters for SELECT");
return;}
if (mysql_stmt_execute (stmt) != 0){
print_stmt_error (stmt, "Could not execute SELECT");
return;}
if (mysql_stmt_store_result (stmt) != 0){
print_stmt_error (stmt, "Could not buffer result set");
return;}
else{
printf ("Number of rows retrieved: %lu\n",
(unsigned long) mysql_stmt_num_rows (stmt));}
int ii = mysql_stmt_fetch (stmt);
while (ii == 0 || ii==MYSQL_DATA_TRUNCATED) /* fetch each row */
{
/* display row values */
printf ("%d ", my_int);
printf ("%.2f ", my_float);
printf ("%04d-%02d-%02d %02d:%02d:%02d\n",
my_datetime.year,
my_datetime.month,
my_datetime.day,
my_datetime.hour,
my_datetime.minute,
my_datetime.second);
ii=mysql_stmt_fetch (stmt);
}
mysql_stmt_free_result (stmt); /* deallocate result set */
}
事实证明这是一个令人沮丧的简单错误。我的 MYSQL_BIND
结构的顺序不正确,mysql_stmt_bind_param()
没有返回错误来指示数据类型不匹配。您可以看到浮点数在我的数据库中的字段 3 中,但在我的 param[]
数组中的第二个字段中。切换 MYSQL_BIND
结构的顺序解决了我的问题。
我 post 这个解决方案而不是删除这个问题,因为在网上其他地方找不到关于 MYSQL 截断错误的信息,而其他人可能会犯这个微妙但简单的错误。