Laravel调用多结果集存储过程仅返回首个结果集如何解决
问题现象
- MySQL中创建了自定义存储过程
my_procedure,内部逻辑为依次调用两个带SELECT查询的子存储过程:
BEGIN CALL procedure_one(); CALL procedure_two(); END
- 直接在MySQL客户端执行
CALL my_procedure()可正常返回两个子存储过程的查询结果 - 在Laravel中使用以下两种方式调用时,仅能返回第一个存储过程的执行结果:
DB::select("CALL my_procedure"); DB::select(DB::raw("CALL my_procedure"));
根本原因
Laravel封装的DB::select()方法默认仅抓取SQL执行返回的第一个结果集,不会主动遍历MySQL多结果集响应中的后续内容;同时PDO驱动执行返回多结果集的存储过程时,如果不主动遍历释放所有结果集,还可能导致后续同连接的数据库操作出现"无法在其他无缓冲查询激活时执行查询"的报错。
解决方案
通过PDO原生接口遍历所有结果集即可拿到全部返回内容,示例代码如下:
// 获取当前数据库连接的PDO实例 $pdo = DB::connection()->getPdo(); // 预处理存储过程调用语句,有入参时可以在SQL中用?占位 $stmt = $pdo->prepare("CALL my_procedure()"); $stmt->execute(); // 有入参时传参示例:$stmt->execute([$param1, $param2]); $allResults = []; // 循环拉取所有结果集 do { $currentResult = $stmt->fetchAll(\PDO::FETCH_OBJ); if (!empty($currentResult)) { $allResults[] = $currentResult; } // 移动到下一个结果集,直到没有更多结果为止 } while ($stmt->nextRowset() && $stmt->columnCount()); // 释放语句句柄,避免影响后续查询 $stmt = null;
执行完成后,$allResults[0]为procedure_one()返回的查询结果,$allResults[1]为procedure_two()返回的查询结果。
注意事项
- 禁止直接使用
DB::select()调用返回多结果集的存储过程,该方法底层未实现多结果集遍历逻辑 - 存储过程执行完成后必须手动释放语句游标资源,否则会触发连接级别的报错
- 若存储过程包含OUT类型参数,可在遍历完所有结果集后,通过
$stmt->fetchAll()获取OUT参数的返回值
内容的提问来源于stack exchange,提问作者Frank Matta
相关产品推荐
相关产品推荐

