
在原生 SQL 中直接用单个占位符(如 :codes)绑定逗号分隔的字符串(如 'test','last')无法正确解析 IN 子句,会导致查询无结果;应改用预处理语句动态生成占位符,或优先使用 Laravel Query Builder 的 whereIn() 方法自动处理参数绑定与类型安全。
在原生 sql 中直接用单个占位符(如 `:codes`)绑定逗号分隔的字符串(如 `'test','last'`)无法正确解析 in 子句,会导致查询无结果;应改用预处理语句动态生成占位符,或优先使用 laravel query builder 的 `wherein()` 方法自动处理参数绑定与类型安全。
在 PHP(尤其是 Laravel 环境)中操作 SQL 的 IN 子句时,一个常见误区是试图将多个值拼接成字符串后,用单个命名参数(如 :codes)传入预处理语句:
$sqlQuery = "SELECT * FROM mytable WHERE codes IN (:codes)"; $params['codes'] = "'test','last'"; // ❌ 错误:数据库会将其视为一个字符串字面量,而非两个独立值 DB::select($sqlQuery, $params);
这实际执行的是等效于 WHERE codes IN ('''test'',''last''') 的查询——即把整个字符串当作单个带引号的值,自然无法匹配任何记录。
✅ 正确做法有两类,推荐按优先级选择:
1. 使用 Laravel Query Builder(首选,安全且简洁)
Laravel 自动为 whereIn() 生成合适数量的占位符并完成类型绑定,无需手动拼接:
立即学习“PHP免费学习笔记(深入)”;
// $codes 是数组,例如 ['test', 'last']
$codes = ['test', 'last'];
$results = DB::table('mytable')
->whereIn('codes', $codes)
->get();
// 或使用 Eloquent 模型(若已定义 MyModel)
$results = MyModel::whereIn('codes', $codes)->get();该方式底层会生成类似 WHERE codes IN (?, ?) 的语句,并分别绑定 'test' 和 'last',完全规避 SQL 注入风险,且支持整数、字符串、UUID 等多种类型自动适配。
2. 原生 SQL + 动态占位符(仅当必须写原生 SQL 时)
若因复杂查询必须使用原生 SQL,则需动态构建占位符序列,再逐个绑定:
$codes = ['test', 'last'];
$placeholders = str_repeat('?,', count($codes) - 1) . '?';
$sqlQuery = "SELECT * FROM mytable WHERE codes IN ($placeholders)";
$total = DB::select($sqlQuery, $codes); // $codes 数组直接作为参数列表⚠️ 注意事项:
-
切勿对用户输入做字符串拼接(如
"'".implode("','", $arr)."'"),极易引发 SQL 注入; -
whereIn()对空数组([])默认返回空集合,行为安全;但某些旧版驱动在空数组时可能报错,建议前置校验; - 若
$codes来自用户请求(如 URL 参数),务必验证其长度和内容格式(如正则限制为字母数字),避免 DoS 攻击(超大数组导致占位符过多)。
总结:IN 子句不是“一个参数”,而是“一组参数”。放弃单占位符幻想,拥抱 whereIn() 或动态占位符机制,是保障查询正确性与安全性的关键实践。



















