c api预处理方式调用存储过程,只能调用一次? 存储过程中就只有一句普通的select * from ...;第一次调用成功,然后mysql_stmt_close()..再调一次,结果mysql_stmt_prepare()这一句,就出现CR_COMMANDS_OUT_OF_SYNC错误。郁闷啊 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 void test() { //... int t1,t2; MYSQL_STMT *hStmt = mysql_stmt_init(m_hSql); char sql[] = "call test(?)"; if ( mysql_stmt_prepare( hStmt,sql,static_cast<unsigned long>(strlen(sql))) != 0 ) printf(mysql_stmt_error(hStmt); ibind.buffer_type = MYSQL_TYPE_LONG; ibind.buffer = t1; if ( mysql_stmt_bind_param(hStmt,&ibind) != 0 ) printf(mysql_stmt_error(hStmt)); if ( mysql_stmt_execute(hStmt) != 0 ) printf(mysql_stmt_error(hStmt)); obind.buffer_type= MYSQL_TYPE_LONG; obind.buffer= (char *)&t2; if (mysql_stmt_bind_result(hStmt, &obind) !=0 ) printf(mysql_stmt_error(hStmt)); if (mysql_stmt_store_result(hStmt) !=0 ) printf(mysql_stmt_error(hStmt)); rows = mysql_stmt_num_rows(hStmt); for( my_ulonglong i=0; i<rows; ++i ) { nRet = mysql_stmt_fetch(hStmt); //... } mysql_stmt_close(hStmt);}//存储过程CREATE DEFINER=`root`@`localhost` PROCEDURE test( in t1 int)BEGIN select t2 from test from id=t1;END如果test()连着调两次,就会报错 if ( mysql_stmt_execute(hStmt) != 0 ) printf(mysql_stmt_error(hStmt)); 在正确执行后,要释放这个预处理。DEALLOCATE PREPARE hStmt; 直接调用sql code释放?hStmt是在c中的句柄呀,有对应的c api函数吗? mysql_stmt_close已经足够了。问题不在这儿,而是中间的调用顺序出了问题:应该是:1. stmt_bind_param2. stmt_execute3. stmt_store_result4. stmt_bind_result5. stmt_close你先按这个顺序处理一遍试试吧。 顺序是对的,第二次再调用这个函数的时候,mysql_stmt_prepare这里就出错了。如果不是调用存储过程"call test(?)"的话,直接调用用"select t2 from test from id=?"命令的话,没有发现问题。 你的mysql版本是多少?我可以拿到本地来试一下。从错误来看,是由于函数调用顺序不当造成的。 我在本地试了一下,使用的是版本:mysql-5.1.26-rc-win32。你的代码有一个地方确实有问题。这可能也需要我们总结一下。1. 使用存储过程call test(?)返回结果集,需要创建CLIENT_MULTI_STATEMENTS的客户端连接2. 在两次调用call test(?),要释放中间产生的若干结果集。具体做法如下:在mysql_stmt_close之前,最好调用一次:mysql_stmt_free_result(hStmt);在mysql_stmt_close()调用完以后,立即使用如下循环释放其它我们不需要的MYSQL_RESULT: do { MYSQL_RES* res = mysql_store_result(mysql_); mysql_free_result(res); } while ( (0 == mysql_next_result(mysql_)) );如果没有这一段释放,连续调用,则会出现楼主所说的错误。总之,调用存储过程产生结果集跟调用select查询产生结果集,还是有一些不一样。前者可能产生多个结果集。 很感谢iihero,我使用的是5.5.3版。使用mysql_stmt_free_result(hStmt);没有什么作用。不过:do { MYSQL_RES* res = mysql_store_result(mysql_); mysql_free_result(res); } while ( (0 == mysql_next_result(mysql_)) );确实能解决问题,呵呵!留下个疑问,这样一个连接就无法让多线程共享数据了,因为无法确定多线程是否安全。 你的版本很新啊,呵呵。我来不及更新版本。前边的free_result是调用惯用法。意即在close之前,进行free,释放掉不必要的cursor之类的东东。后边的while是必须的。一个连接当然不能多线程共享了。可以每线程一个单独的连接进行处理。多线程共享连接,那么中间产生的许多资源就成了共享资源了,需要进行锁定,处理极为不便。 这种做法解决了问题,不过或许可以算是预处理函数的一种bug,按常理mysql_stmt_close()或者mysql_stmt_free_result()应该会自动释放掉产生的资源,只是没想到还要使用非预处理函数来处理相关的资源。至于多个线程用同一个连接,手册上也介绍了相关介绍,可以使用,不过要自行加锁处理。复杂度也就更高了。 设计一个备份系统,我的想法和问题 请大家给指点 mysql自己生成的seq_表怎么回事? 怎么动态创建列 未找到匹配的结果,能否让查询字段返回0? MySQL問題,了解的來看下 MYSQL新手问题! 问个 mysql 查询的问题,希望会的兄弟可以写完整一些 一个奇怪的错误 求帮助,帮忙分析分析 mysql 查询字符串=数字,比如name=880725279310348288 2天前看到一个帖子是总结sql语句的,貌似还推荐了,现在怎么没了? MySQL主从服务器自动同步的一个方案,请大虾们指出不足之处,谢谢!
{
//...
int t1,t2; MYSQL_STMT *hStmt = mysql_stmt_init(m_hSql);
char sql[] = "call test(?)";
if ( mysql_stmt_prepare( hStmt,sql,static_cast<unsigned long>(strlen(sql))) != 0 )
printf(mysql_stmt_error(hStmt); ibind.buffer_type = MYSQL_TYPE_LONG;
ibind.buffer = t1; if ( mysql_stmt_bind_param(hStmt,&ibind) != 0 )
printf(mysql_stmt_error(hStmt)); if ( mysql_stmt_execute(hStmt) != 0 )
printf(mysql_stmt_error(hStmt)); obind.buffer_type= MYSQL_TYPE_LONG;
obind.buffer= (char *)&t2; if (mysql_stmt_bind_result(hStmt, &obind) !=0 )
printf(mysql_stmt_error(hStmt)); if (mysql_stmt_store_result(hStmt) !=0 )
printf(mysql_stmt_error(hStmt)); rows = mysql_stmt_num_rows(hStmt);
for( my_ulonglong i=0; i<rows; ++i )
{
nRet = mysql_stmt_fetch(hStmt);
//...
}
mysql_stmt_close(hStmt);
}//存储过程
CREATE DEFINER=`root`@`localhost` PROCEDURE test( in t1 int)
BEGIN
select t2 from test from id=t1;
END如果test()连着调两次,就会报错
printf(mysql_stmt_error(hStmt));
在正确执行后,要释放这个预处理。DEALLOCATE PREPARE hStmt;
hStmt是在c中的句柄呀,有对应的c api函数吗?
问题不在这儿,而是中间的调用顺序出了问题:
应该是:
1. stmt_bind_param
2. stmt_execute
3. stmt_store_result
4. stmt_bind_result
5. stmt_close你先按这个顺序处理一遍试试吧。
如果不是调用存储过程"call test(?)"的话,直接调用用"select t2 from test from id=?"命令的话,没有发现问题。
你的代码有一个地方确实有问题。
这可能也需要我们总结一下。
1. 使用存储过程call test(?)返回结果集,需要创建CLIENT_MULTI_STATEMENTS的客户端连接
2. 在两次调用call test(?),要释放中间产生的若干结果集。具体做法如下:
在mysql_stmt_close之前,最好调用一次:mysql_stmt_free_result(hStmt);
在mysql_stmt_close()调用完以后,立即使用如下循环释放其它我们不需要的MYSQL_RESULT:
do
{
MYSQL_RES* res = mysql_store_result(mysql_);
mysql_free_result(res);
}
while ( (0 == mysql_next_result(mysql_)) );
如果没有这一段释放,连续调用,则会出现楼主所说的错误。总之,调用存储过程产生结果集跟调用select查询产生结果集,还是有一些不一样。
前者可能产生多个结果集。
使用mysql_stmt_free_result(hStmt);没有什么作用。
不过:
do
{
MYSQL_RES* res = mysql_store_result(mysql_);
mysql_free_result(res);
}
while ( (0 == mysql_next_result(mysql_)) );确实能解决问题,呵呵!
留下个疑问,这样一个连接就无法让多线程共享数据了,因为无法确定多线程是否安全。
你的版本很新啊,呵呵。我来不及更新版本。
前边的free_result是调用惯用法。意即在close之前,进行free,释放掉不必要的cursor之类的东东。后边的while是必须的。
一个连接当然不能多线程共享了。
可以每线程一个单独的连接进行处理。多线程共享连接,那么中间产生的许多资源就成了共享资源了,需要进行锁定,处理极为不便。
至于多个线程用同一个连接,手册上也介绍了相关介绍,可以使用,不过要自行加锁处理。复杂度也就更高了。