2022-07-30 15:14:06
在PHP PDO中正确使用WHERE与HAVING子句参数绑定及LIKE操作的核心方法是:确保命名占位符键名严格匹配(含冒号),将LIKE通配符(%)与搜索值在PHP代码中拼接后绑定,避免直接在SQL中嵌入通配符。
一、参数绑定的核心原则占位符类型选择
PDO支持两种占位符:问号占位符(?)和命名占位符(:name)。
推荐命名占位符:在复杂查询中(如同时使用WHERE和HAVING),命名占位符可读性更强,便于维护。
命名占位符的键名匹配规则
SQL查询中定义的占位符(如:currency_pattern)必须与execute()方法中关联数组的键名完全一致,包括冒号。
错误示例:若SQL中为:my_param,但数组键为'my_param'(缺少冒号),会触发“Invalid parameter number”错误。
基本语法结构
WHERE子句过滤原始表数据,HAVING子句过滤分组后的结果,两者参数绑定方式相同。
示例SQL:SELECT `_md_currencies`.`_fd_currency`, IFNULL((SELECT GROUP_CONCAT(_md_tasks_level1._fd_name SEPARATOR ' + ') FROM _x_md_currencies_x_md_tasks LEFT JOIN _md_tasks AS _md_tasks_level1 ON _x_md_currencies_x_md_tasks.ID_md_tasks = _md_tasks_level1.ID WHERE _x_md_currencies_x_md_tasks.ID_md_currencies = _md_currencies.ID), '') AS Many2Many_CurrencyFROM `_md_currencies`WHERE `_md_currencies`.`_fd_currency` LIKE :currency_patternHAVING Many2Many_Currency LIKE :task_pattern;
定义了两个命名占位符::currency_pattern(WHERE子句)和:task_pattern(HAVING子句)。
绑定参数的PHP实现
在PHP中,需将通配符(%)与搜索值拼接后绑定到占位符,而非直接在SQL中嵌入通配符。
正确示例:$currencySearchTerm = 'Currency 1';$taskSearchTerm = 'Task';$ValueRequette = [ ':currency_pattern' => '%' . $currencySearchTerm . '%', // 通配符拼接 ':task_pattern' => '%' . $taskSearchTerm . '%'];
常见错误场景
错误做法:将通配符直接写入SQL的LIKE模式中,如:WHERE `_md_currencies`.`_fd_currency` LIKE '% :currency_pattern %'
问题:PDO会将'% :currency_pattern %'视为字面量字符串,而非占位符,导致参数数量不匹配错误。
正确实践
通配符拼接位置:在PHP代码中将%与搜索值拼接,形成完整模式后绑定。
示例代码:$searchTerm = 'example';$params = [':pattern' => '%' . $searchTerm . '%'];$stmt->execute($params);
PHP与SQL整合代码
$MyRequetteRecords = 'SELECT `_md_currencies`.`_fd_currency`, IFNULL((SELECT GROUP_CONCAT(_md_tasks_level1._fd_name SEPARATOR ' + ') FROM _x_md_currencies_x_md_tasks LEFT JOIN _md_tasks AS _md_tasks_level1 ON _x_md_currencies_x_md_tasks.ID_md_tasks = _md_tasks_level1.ID WHERE _x_md_currencies_x_md_tasks.ID_md_currencies = _md_currencies.ID), '') AS Many2Many_Currency FROM `_md_currencies` WHERE `_md_currencies`.`_fd_currency` LIKE :currency_pattern HAVING Many2Many_Currency LIKE :task_pattern;';$currencySearchTerm = 'Currency 1';$taskSearchTerm = 'Task';$ValueRequette = [ ':currency_pattern' => '%' . $currencySearchTerm . '%', ':task_pattern' => '%' . $taskSearchTerm . '%'];try { $statement = $bdd_dataManger->prepare($MyRequetteRecords); $statement->execute($ValueRequette); $records = $statement->fetchAll(PDO::FETCH_ASSOC); print_r($records); $statement->closeCursor();} catch (PDOException $e) { echo "数据库错误: " . $e->getMessage();}关键点解析
SQL字符串处理:使用单引号包裹整个SQL,内部字符串(如' + ')用反斜杠转义。
占位符匹配:$ValueRequette数组的键(如:currency_pattern)与SQL中的占位符完全一致。
通配符拼接:在PHP中完成%与搜索值的拼接,确保LIKE模式正确。
SQL语法验证
在PHP执行前,先在数据库客户端(如MySQL Workbench)中测试SQL查询,确保语法正确。
错误处理
使用try-catch捕获PDOException,避免直接输出错误信息(生产环境应记录日志)。
安全性
预处理语句是防止SQL注入的核心手段,务必正确使用参数绑定。
总结:正确使用PHP PDO的参数绑定需遵循两点: