如何在Laravel查询构造器中使用MySQL SET变量?
Laravel中DB::statement定义的MySQL会话变量在查询构造器中返回NULL的问题
我在DB::statement()中定义了@num和@type两个MySQL会话变量,后续用Laravel查询构造器调用这两个变量时,它们全返回NULL,拿不到预期值。
实际输出
| id | number | type |
|---|---|---|
| 1 | (NULL) | (NULL) |
| 2 | (NULL) | (NULL) |
| 3 | (NULL) | (NULL) |
| 4 | (NULL) | (NULL) |
| 5 | (NULL) | (NULL) |
| 6 | (NULL) | (NULL) |
| 7 | (NULL) | (NULL) |
| 8 | (NULL) | (NULL) |
| 9 | (NULL) | (NULL) |
| 10 | (NULL) | (NULL) |
期望输出
| id | number | type |
|---|---|---|
| 1 | 1 | 2 |
| 2 | 1 | 2 |
| 3 | 1 | 2 |
| 4 | 1 | 2 |
| 5 | 1 | 2 |
| 6 | 1 | 2 |
| 7 | 1 | 2 |
| 8 | 1 | 2 |
| 9 | 1 | 2 |
| 10 | 1 | 2 |
相关代码截图


问题原因
Laravel默认的数据库连接受连接池机制影响,分开执行的DB::statement()和查询构造器调用,可能会使用不同的数据库会话。而MySQL的会话变量@xxx仅在当前会话中有效,切换会话后自然取不到值。
解决方法
1. 强制所有操作在同一会话执行
用DB::transaction()包裹所有操作,事务会强制使用同一个数据库连接会话:
DB::transaction(function () { // 定义会话变量 DB::statement('SET @num = 1, @type = 2'); // 执行查询 $data = DB::table('your_table_name') ->select('id', DB::raw('@num as number'), DB::raw('@type as type')) ->get(); // 输出结果 dd($data); });
或者手动获取连接实例,复用同一个连接:
$conn = DB::connection(); // 定义变量 $conn->statement('SET @num = 1, @type = 2'); // 用同一个连接查数据 $data = $conn->table('your_table_name') ->select('id', DB::raw('@num as number'), DB::raw('@type as type')) ->get();
2. 把变量定义和查询合并成一个语句
直接用DB::select()执行复合语句,确保在同一会话中完成:
// 执行复合SQL,先定义变量再查询 $result = DB::select('SET @num = 1, @type = 2; SELECT id, @num as number, @type as type FROM your_table_name'); // 返回的是数组,第二个元素是查询结果集 $finalData = $result[1];
3. 用Laravel查询绑定替代会话变量
如果不需要持久化会话变量,直接用查询绑定更符合Laravel最佳实践,也不会有跨会话问题:
$num = 1; $type = 2; $data = DB::table('your_table_name') ->select( 'id', DB::raw('? as number', [$num]), DB::raw('? as type', [$type]) ) ->get();
内容的提问来源于stack exchange,提问作者Test
相关产品推荐
相关产品推荐

