除了重用之外,这里的主要问题是您试图动态地更改col名称。 以下是一位匿名用户在http://php.net/manual/en/pdo.prepare.php上发布的答案: 对于那些想知道为什么在占位符周围添加引号是错误的,以及为什么不能在表或列名中使用占位符的人: 对于预处理语句中的占位符的工作方式有一个常见的误解:它们不是简单地作为(转义的)字符串被替换,并执行结果SQL。相反,被要求“准备”语句的DBMS会给出一个完整的查询计划,说明它将如何执行该查询,包括它将使用哪些表和索引,无论如何填充占位符,这些都是相同的。 无论你用什么替换“:value”,“SELECT name FROM my_table WHERE id =:value”的计划都是一样的,但是看起来类似的“SELECT name FROM:table WHERE id =:value”不能被计划,因为DBMS不知道你实际上要从哪个表中选择。 即使使用“模拟准备”,PDO也不能让你在任何地方使用占位符,因为它必须解决你的意思:“Select:foo From some_table”是否意味着“:foo”将是列引用,还是文字字符串? 当你的查询使用动态列引用时,你应该显式地将你知道存在于表中的列在白名单中,例如。使用switch语句,并在默认情况下抛出异常:条款。
function search($criteria) {
$sql = "SELECT * FROM my_table
WHERE column_1 like CONCAT('%', :criteria1, '%')
OR column_2 like CONCAT('%', :criteria2, '%')
OR column_3 like CONCAT('%', :criteria3, '%')
";
$stmt = $this->db->prepare($sql);
$stmt->bindParam(':criteria1', $criteria);
$stmt->bindParam(':criteria2', $criteria);
$stmt->bindParam(':criteria3', $criteria);
$stmt->execute();
return($stmt->fetchAll(PDO::FETCH_ASSOC));
}
6条答案
按热度按时间mrphzbgm1#
PDO::prepare声明“你不能在一个预处理语句中两次使用相同名称的命名参数标记”,所以我猜这是一个否定的答案。
vs91vp4v2#
如果设置
PDO::ATTR_EMULATE_PREPARES = true
,则可以。例如:
$connection->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
。如果你使用Laravel,你可以在
config/database.php
中的options
数组中设置这个值。例如PDO::ATTR_EMULATE_PREPARES => true
iyzzxitl3#
除了重用之外,这里的主要问题是您试图动态地更改col名称。
以下是一位匿名用户在http://php.net/manual/en/pdo.prepare.php上发布的答案:
对于那些想知道为什么在占位符周围添加引号是错误的,以及为什么不能在表或列名中使用占位符的人:
对于预处理语句中的占位符的工作方式有一个常见的误解:它们不是简单地作为(转义的)字符串被替换,并执行结果SQL。相反,被要求“准备”语句的DBMS会给出一个完整的查询计划,说明它将如何执行该查询,包括它将使用哪些表和索引,无论如何填充占位符,这些都是相同的。
无论你用什么替换“:value”,“SELECT name FROM my_table WHERE id =:value”的计划都是一样的,但是看起来类似的“SELECT name FROM:table WHERE id =:value”不能被计划,因为DBMS不知道你实际上要从哪个表中选择。
即使使用“模拟准备”,PDO也不能让你在任何地方使用占位符,因为它必须解决你的意思:“Select:foo From some_table”是否意味着“:foo”将是列引用,还是文字字符串?
当你的查询使用动态列引用时,你应该显式地将你知道存在于表中的列在白名单中,例如。使用switch语句,并在默认情况下抛出异常:条款。
esbemjvw4#
许多像您这样的查询可以重写为仅使用一个占位符。
就等于
但有时候事情没那么简单。举例来说:
在这种情况下,您可以重用参数值,将其存储在交叉连接的派生表中(FROM子句中的子查询):
wxclj1h55#
正如其他人所指出的,有很多变通方法:
1.使用不同的占位符,同时为它们提供相同的值。
1.重写查询,以便只需要唯一的占位符。
1.将
ATTR_EMULATE_PREPARES
设置为true
如果上面的方法不可行也不可取,还有另一种优雅的方法来解决这个问题,通过使用SQL中的变量:
然后通过赋值
value
来准备这个语句。0tdrvxhp6#
有一个解决方法:
总之,使用具有相同条件的不同占位符。