Laravel中使用MySQL变量执行原生查询报1064语法错误如何解决
你遇到的语法报错是因为Laravel默认禁用了PDO的多语句执行能力,你在单个DB::statement调用中传入了两条SET语句,相当于一次执行多条SQL,不符合默认的执行规则,就会抛出语法错误。
你之前尝试把SET和查询放在同一段SQL里报错也是同样的原因。
方案1:拆分SET语句单独执行(最推荐,无额外安全风险)
把两条SET语句分开,每条单独调用一次DB::statement执行,不需要修改任何连接配置,变量会在当前数据库连接的生命周期内生效,后续查询可以正常调用:
// 单独设置每个SQL变量 DB::statement('SET @lon = ?', [$longitude]); DB::statement('SET @lat = ?', [$latitude]); // 后续查询逻辑保持不变,不需要套DB::raw,原生查询方法本身支持直接传SQL和参数绑定 $places = DB::select( " SELECT id FROM places WHERE position = POINT(@lon, @lat) AND language = ? AND LOWER(name) LIKE LOWER(CONCAT(?, '%')) ORDER BY distance LIMIT 10; ", [$language, $name] );
方案2:临时开启多语句执行(适合多语句场景,注意防范注入风险)
如果需要执行的SET语句数量较多,拆分执行太繁琐,可以临时开启当前连接的多语句执行权限,用完后建议立刻关闭,降低SQL注入风险:
// 临时开启多语句支持 DB::connection()->getPdo()->setAttribute(\PDO::MYSQL_ATTR_MULTI_STATEMENTS, true); // 一次性执行多条SET语句 DB::statement( " SET @lon = ?; SET @lat = ?; ", [$longitude, $latitude] ); // 执行完成后关闭多语句支持 DB::connection()->getPdo()->setAttribute(\PDO::MYSQL_ATTR_MULTI_STATEMENTS, false); // 后续查询逻辑不变 $places = DB::select( " SELECT id FROM places WHERE position = POINT(@lon, @lat) AND language = ? AND LOWER(name) LIKE LOWER(CONCAT(?, '%')) ORDER BY distance LIMIT 10; ", [$language, $name] );
内容的提问来源于stack exchange,提问作者theberzi
相关产品推荐
相关产品推荐

