【发布时间】:2016-07-08 22:27:11
【问题描述】:
我正在开发一个与 mysql 交互的 C 项目。所以我打算使用mysql存储过程并在link中找到了一个示例程序 我只是根据我的项目要求更改了程序。这是表结构
id | int(10) unsigned | NO | PRI | NULL | auto_increment |
username | varchar(64) | NO | MUL | NULL | |
password | varchar(25) | NO | | NULL | |
这是我的程序。
int main()
{
MYSQL_RES *result;
MYSQL *mysql=mysql_init(NULL);
/* connect to server with the CLIENT_MULTI_STATEMENTS option */
if (mysql_real_connect (mysql, "localhost", "root", "root123","DONT_USE", 0, NULL , CLIENT_MULTI_STATEMENTS) == NULL)
{
printf("mysql_real_connect() failed\n");
mysql_close(mysql);
}
MYSQL_STMT *stmt;
MYSQL_BIND ps_params[1]; /* input parameter buffers */
long int int_data[3]; /* input/output values */
my_bool is_null[3]; /* output value nullability */
int status;
char own_buf[25],input_buf[64];
memset(own_buf, 0, 25);
memset(input_buf, 0, 64);
/* set up stored procedure */
status = mysql_query(mysql, "DROP PROCEDURE IF EXISTS p1");
test_error(mysql, status);
status = mysql_query(mysql,
"CREATE PROCEDURE p1("
" IN p_in VARCHAR(64)) "
"BEGIN "
" SELECT password from data where username=p_in; "
"END");
test_error(mysql, status);
/* initialize and prepare CALL statement with parameter placeholders */
stmt = mysql_stmt_init(mysql);
if (!stmt)
{
printf("Could not initialize statement\n");
}
status = mysql_stmt_prepare(stmt, "CALL p1(?)", 10);
test_stmt_error(stmt, status);
/* initialize parameters: p_in, p_out, p_inout (all INT) */
memset(ps_params, 0, sizeof (ps_params));
ps_params[0].buffer_type = MYSQL_TYPE_STRING;
ps_params[0].buffer = (void *) &input_buf;
ps_params[0].buffer_length = sizeof(input_buf);
ps_params[0].is_null = 0;
/* bind parameters */
status = mysql_stmt_bind_param(stmt, ps_params);
test_stmt_error(stmt, status);
/* assign values to parameters and execute statement */
int_data[0]= 2; /* p_in */
int_data[1]= 20; /* p_out */
strcpy(input_buf,"'6666600222'");
int_data[0] = strlen(input_buf);
input_buf[int_data[0]] = '\0';
ps_params[0].length = &int_data[0];
status = mysql_stmt_execute(stmt);
test_stmt_error(stmt, status);
/* process results until there are no more */
do {
int i;
int num_fields; /* number of columns in result */
MYSQL_FIELD *fields; /* for result set metadata */
MYSQL_BIND *rs_bind; /* for output buffers */
/* the column count is > 0 if there is a result set */
/* 0 if the result is only the final status packet */
num_fields = mysql_stmt_field_count(stmt);
if (num_fields > 0)
{
/* there is a result set to fetch */
printf("Number of columns in result: %d\n", (int) num_fields);
/* what kind of result set is this? */
printf("Data: ");
if(mysql->server_status & SERVER_PS_OUT_PARAMS)
printf("this result set contains OUT/INOUT parameters\n");
else
printf("this result set is produced by the procedure\n");
MYSQL_RES *rs_metadata = mysql_stmt_result_metadata(stmt);
test_stmt_error(stmt, rs_metadata == NULL);
fields = mysql_fetch_fields(rs_metadata);
rs_bind = (MYSQL_BIND *) malloc(sizeof (MYSQL_BIND) * num_fields);
if (!rs_bind)
{
printf("Cannot allocate output buffers\n");
}
memset(rs_bind, 0, sizeof (MYSQL_BIND) * num_fields);
/* set up and bind result set output buffers */
for (i = 0; i < num_fields; ++i)
{
rs_bind[i].buffer_type = fields[i].type;
rs_bind[i].is_null = &is_null[i];
switch (fields[i].type)
{
case MYSQL_TYPE_LONG:
rs_bind[i].buffer = (char *) &(int_data[i]);
rs_bind[i].buffer_length = sizeof (int_data);
break;
case MYSQL_TYPE_VAR_STRING:
rs_bind[i].buffer = (char *) own_buf;
rs_bind[i].buffer_length = sizeof(own_buf);
rs_bind[i].length = &int_data[1];
break;
default:
fprintf(stderr, "ERROR: unexpected type: %d.\n", fields[i].type);
}
}
status = mysql_stmt_bind_result(stmt, rs_bind);
test_stmt_error(stmt, status);
/* fetch and display result set rows */
while (1)
{
status = mysql_stmt_fetch(stmt);
if (status == 1 || status == MYSQL_NO_DATA)
break;
for (i = 0; i < num_fields; ++i)
{
switch (rs_bind[i].buffer_type)
{
case MYSQL_TYPE_LONG:
if (*rs_bind[i].is_null)
printf(" val[%d] = NULL;", i);
else
printf(" val[%d] = %ld;",
i, (long) *((int *) rs_bind[i].buffer));
break;
case MYSQL_TYPE_VAR_STRING:
printf(" val[%d] = %s;",i,(char*)rs_bind[i].buffer);
break;
default:
printf(" unexpected type (%d)\n",
rs_bind[i].buffer_type);
}
}
printf("\n");
}
mysql_free_result(rs_metadata); /* free metadata */
free(rs_bind); /* free output buffers */
}
else
{
/* no columns = final status packet */
printf("End of procedure output\n");
}
/* more results? -1 = no, >0 = error, 0 = yes (keep looking) */
status = mysql_stmt_next_result(stmt);
if (status > 0)
test_stmt_error(stmt, status);
} while (status == 0);
mysql_stmt_close(stmt);
}
OUTPUT:
Number of columns in result: 1
Data: this result set is produced by the procedure
End of procedure output
对于像 CREATE PROCEDURE p1(IN p_in INT) 这样的整数参数,上面的代码可以正常工作,但对于 varchar 参数则不行。
link 链接中提到的 varchar 输入参数类型是 MYSQL_TYPE_STRING,输出参数类型是 MYSQL_TYPE_VAR_STRING
问题: 得到空的结果。 据我分析,status = mysql_stmt_fetch(stmt);函数通过表中存在的条目返回 100(MYSQL_NO_DATA)。
注意:我尝试将程序手动调用到 mysql 中,例如 call p1('6666600222');结果
mysql> call p1('6666600222');
+----------+
| password |
+----------+
| 1234 |
+----------+
1 row in set (0.00 sec)
有人帮我把这个短路吗?
【问题讨论】:
-
您确定在 varchar ps_params 的情况下应该采用指向 char 的指针而不是指向 char 的指针吗?您是否尝试过以下操作:
const char * x = &(input_buf[0]);ps_params[0] = (void *)&x; -
感谢回复。我试过 (void*)&x;但它仍然保持不变@MysticOdin
-
这是正确的做法吗?或者我可以使用任何其他方法来实现这一点吗?
-
我将过程更改为 INSERT 而不是 SELECT。它工作正常。如果查询包含 '=' 运算符,例如 'where' ,则 'set' 会产生空值。任何人都知道如何使用 C API 在哪里进行选择
标签: mysql c stored-procedures