默认情况下,mysql_real_query()
将mysql_query()
它们的语句字符串参数解释为要执行的单个语句,并根据语句是否生成结果集(一组行,如
SELECT
)或受影响的行数(如INSERT
,
UPDATE
,等等)。
;
MySQL 还支持执行一个字符串,该字符串包含以分号 ( ) 字符
分隔的多个语句。此功能由特殊选项启用,这些选项在您使用 连接到服务器时
mysql_real_connect()
或通过调用 连接后
指定mysql_set_server_option()
。
执行多语句字符串可以产生多个结果集或行计数指示符。处理这些结果涉及与单语句情况不同的方法:处理完第一个语句的结果后,有必要检查是否存在更多结果,如果存在则依次处理它们。为了支持多结果处理,C API 包括
mysql_more_results()
和
mysql_next_result()
函数。只要有更多结果可用,这些函数就会在循环结束时使用。未能以这种方式处理结果可能会导致与服务器的连接中断。
CALL
如果您执行存储过程的语句,
也需要多结果处理
。存储过程的结果具有以下特征:
-
过程中的语句可能会产生结果集(例如,如果它执行
SELECT
语句)。这些结果集按照过程执行时产生的顺序返回。通常,调用者无法知道过程将返回多少个结果集。过程执行可能依赖于循环或条件语句,这些循环或条件语句导致执行路径从一个调用到下一个调用不同。因此,您必须准备好检索多个结果。
该过程的最终结果是不包含结果集的状态结果。状态指示过程是成功还是发生错误。
多语句和结果功能只能与mysql_real_query()
or
一起使用mysql_query()
。它们不能与准备好的语句接口一起使用。准备好的语句处理程序被定义为仅适用于包含单个语句的字符串。请参阅
第 6 章,C API 准备语句接口。
要启用多语句执行和结果处理,可以使用以下选项:
-
该
mysql_real_connect()
函数有一个flags
参数,两个选项值相关:CLIENT_MULTI_RESULTS
使客户端程序能够处理多个结果。如果为生成结果集的存储过程执行语句,则 必须启用此选项 。CALL
否则,此类过程会导致错误。在 MySQL 5.7 中, 默认启用。Error 1312 (0A000): PROCEDURE
proc_name
can't return a result set in the given contextCLIENT_MULTI_RESULTS
CLIENT_MULTI_STATEMENTS
启用mysql_real_query()
并mysql_query()
执行包含多个以分号分隔的语句的语句字符串。CLIENT_MULTI_RESULTS
此选项还隐式 启用 ,因此to 的flags
参数 等同于 的参数 。也就是说, 足以启用多语句执行和所有多结果处理。CLIENT_MULTI_STATEMENTS
mysql_real_connect()
CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS
CLIENT_MULTI_STATEMENTS
建立与服务器的连接后,您可以使用该 函数通过向其传递参数或
mysql_set_server_option()
来启用或禁用多语句执行 。使用此函数启用多语句执行还可以处理多语句字符串的“简单”结果,其中每个语句生成一个结果,但不足以允许处理生成结果集的存储过程。MYSQL_OPTION_MULTI_STATEMENTS_ON
MYSQL_OPTION_MULTI_STATEMENTS_OFF
以下过程概述了处理多个语句的建议策略:
传递
CLIENT_MULTI_STATEMENTS
给mysql_real_connect()
, 以完全启用多语句执行和多结果处理。在调用
mysql_real_query()
ormysql_query()
并验证它成功后,进入一个循环,在该循环中处理语句结果。对于循环的每次迭代,处理当前语句结果,检索结果集或受影响的行数。如果发生错误,则退出循环。
在循环结束时,调用
mysql_next_result()
以检查是否存在另一个结果,如果存在则启动检索。如果没有更多结果可用,则退出循环。
上述策略的一种可能实现如下所示。循环的最后部分可以简化为是否
mysql_next_result()
返回非零值的简单测试。编写的代码区分没有更多的结果和错误,这使得可以为后一次出现的消息打印一条消息。
/* connect to server with the CLIENT_MULTI_STATEMENTS option */
if (mysql_real_connect (mysql, host_name, user_name, password,
db_name, port_num, socket_name, CLIENT_MULTI_STATEMENTS) == NULL)
{
printf("mysql_real_connect() failed\n");
mysql_close(mysql);
exit(1);
}
/* execute multiple statements */
status = mysql_query(mysql,
"DROP TABLE IF EXISTS test_table;\
CREATE TABLE test_table(id INT);\
INSERT INTO test_table VALUES(10);\
UPDATE test_table SET id=20 WHERE id=10;\
SELECT * FROM test_table;\
DROP TABLE test_table");
if (status)
{
printf("Could not execute statement(s)");
mysql_close(mysql);
exit(0);
}
/* process each statement result */
do {
/* did current statement return data? */
result = mysql_store_result(mysql);
if (result)
{
/* yes; process rows and free the result set */
process_result_set(mysql, result);
mysql_free_result(result);
}
else /* no result set or error */
{
if (mysql_field_count(mysql) == 0)
{
printf("%lld rows affected\n",
mysql_affected_rows(mysql));
}
else /* some error occurred */
{
printf("Could not retrieve result set\n");
break;
}
}
/* more results? -1 = no, >0 = error, 0 = yes (keep looping) */
if ((status = mysql_next_result(mysql)) > 0)
printf("Could not execute statement\n");
} while (status == 0);
mysql_close(mysql);