MySQL存储过程多结果集需显式启用multipleStatements=true,否则后续结果集被静默丢弃;各语言客户端配置及调用顺序必须严格遵循协议规范。

MySQL存储过程多结果集必须显式启用连接参数
不设 multipleStatements=true,第二个 SELECT 会被静默丢弃,连 Warning 都可能被忽略。这不是语法错,是 MySQL 协议默认把 CALL 当作单语句处理。
Node.js(mysql2)要这样配:
const connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'xxx',
database: 'test',
multipleStatements: true // 必须加,缺了就只拿到第一个结果集
});
JDBC 连接 URL 得带参数:jdbc:mysql://host/db?multipleStatements=true
- PyMySQL 需设
multi=True,否则nextset()会报错或返回None - MySQL 8.0+ 在某些云数据库 Proxy(如阿里云 PolarDB Proxy)下会直接拦截多结果集请求,得确认底层是否透传协议
- Spring Boot + MyBatis 3.4+ 要在
<select>标签里声明statementType="CALLABLE",且resultMap用英文逗号分隔多个映射
Java JDBC 必须用 execute() + getMoreResults() 循环推进
用 executeQuery("CALL ...") 只能拿到第一个结果集,后续全丢。JDBC 不自动跳转,漏掉 getMoreResults() 就永远读不到后面的数据。
关键顺序不能乱:
- 先调
cs.execute(),返回boolean表示首个结果是不是ResultSet - 每次循环前必须先用
cs.getResultSet()拿当前结果集,并完整遍历完(否则游标卡住) - 再调
cs.getMoreResults()推进;它返回true才说明还有下一个 -
getMoreResults()本身会关闭当前ResultSet,所以不能在没读完时就调
典型错误写法:rs = cs.getResultSet(); cs.getMoreResults(); rs.next() —— 此时 rs 已失效,抛 SQLException: Operation not allowed after ResultSet closed。
Node.js mysql2 中 results 是数组,但结构容易误读
connection.query('CALL sp_multi(?)', [id], (err, results) => {...}) 的 results 是二维数组:每个结果集是 results[i],而 results[i][j] 才是一行对象。
-
results[0]是第一个SELECT的全部行(数组) -
results[0][0]是第一行数据(对象),不是整个结果集 - 如果某个
SELECT返回空结果,results[i]是空数组[],不是null或undefined - OUT 参数不会出现在
results里,得额外查SELECT @var_name或用connection.execute()(mysql2 v3+)配合namedPlaceholders
别写 results[1].map(...) 前忘了判空,否则 Cannot read property 'map' of undefined。
MyBatis 多 resultMap 映射需严格按顺序对应
MyBatis 把存储过程返回的多个结果集,按执行顺序依次匹配 resultMap 列表。顺序错一位,所有数据就全映射歪了。
XML 示例中:
<select id="getReport" statementType="CALLABLE" resultMap="userMap,orderMap,statMap">
{call get_user_report(?)}
</select>
- 存储过程中第一个
SELECT必须对应userMap,第二个对应orderMap,不能颠倒 - 如果第三个
SELECT实际没返回数据(比如条件不满足),MyBatis 仍会尝试用statMap解析空结果集,可能抛NullPointerException -
resultMap里的<result>字段名必须和 SQL 列名完全一致(区分大小写),别依赖 AS 别名没生效
最易被忽略的是:MyBatis 不校验结果集数量与 resultMap 个数是否匹配。少写一个映射,后面的结果集直接被丢弃,日志里连 warning 都没有。


















