如何在Laravel 8.0及以上版本中调用带任意参数的MySQL存储过程
Laravel 8.0+ 调用含输入输出参数存储过程的最优实现方案
以下方案适配 Laravel 8.x、9.x、10.x 全版本,以最常用的 MySQL 数据库为例,可无缝对齐 SQL Server 等其他主流数据库的语法做微调。
核心实现逻辑
- 输出参数用
DB::raw()包裹加@前缀标识为数据库会话变量(MySQL 场景) - 输入参数走 PDO 参数绑定传入,避免 SQL 注入风险
- 存储过程执行完成后,查询会话变量获取输出参数值
完整代码示例
假设存在存储过程calculate_user_score,接收2个输入参数user_id(INT)、behavior_type(VARCHAR),返回1个输出参数total_score(INT),调用代码如下:
// 引入DB门面,非全局引入场景需提前声明 use Illuminate\Support\Facades\DB; // 1. 定义输入参数值 $userId = 123; $behaviorType = 'purchase'; // 2. 执行存储过程,绑定输入参数、声明输出会话变量 DB::statement('CALL calculate_user_score(?, ?, @total_score)', [$userId, $behaviorType]); // 3. 查询获取输出参数值 $result = DB::select('SELECT @total_score as total_score'); $totalScore = $result[0]->total_score;
多输出参数场景直接扩展即可,示例:
DB::statement('CALL multi_output_proc(?, ?, @out1, @out2)', [$inParam1, $inParam2]); $result = DB::select('SELECT @out1 as out1, @out2 as out2');
注意事项
- 输入参数禁止手动拼接SQL,必须走参数绑定传入,规避SQL注入风险
- 输出参数绑定的
@前缀会话变量生命周期和当前数据库连接绑定,同连接下多次调用不会互相干扰 - SQL Server 场景仅需调整调用语法为
DB::statement('EXEC proc_name ?, ?, ? OUTPUT', [$in1, $in2, $outParam]),其余逻辑完全一致 - 事务场景下存储过程调用和普通SQL操作逻辑一致,直接用
DB::transaction()包裹即可
内容的提问来源于stack exchange,提问作者noxter
相关产品推荐
相关产品推荐

