php PDO参数化查询-重用命名占位符?

iecba09b  于 2023-09-29  发布在  PHP
关注(0)|答案(6)|浏览(128)

本质上,我有一个值,我必须在SQL查询中调用几次。因此,是否可以在语句中重用相同的命名占位符,例如。SELECT :Param FROM Table WHERE Column = :Param,然后简单地使用bindValue(“:Param”),并将值用于两个值:Params?

mrphzbgm

mrphzbgm1#

PDO::prepare声明“你不能在一个预处理语句中两次使用相同名称的命名参数标记”,所以我猜这是一个否定的答案。

vs91vp4v

vs91vp4v2#

如果设置PDO::ATTR_EMULATE_PREPARES = true,则可以。
例如:$connection->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
如果你使用Laravel,你可以在config/database.php中的options数组中设置这个值。例如PDO::ATTR_EMULATE_PREPARES => true

iyzzxitl

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语句,并在默认情况下抛出异常:条款。

esbemjvw

esbemjvw4#

许多像您这样的查询可以重写为仅使用一个占位符。

SELECT :Param FROM Table WHERE Column = :Param

就等于

SELECT Column FROM Table WHERE Column = :Param

但有时候事情没那么简单。举例来说:

SELECT *
FROM my_table
WHERE first_name LIKE :Param
   OR last_name  LIKE :Param
   OR biography  LIKE :Param

在这种情况下,您可以重用参数值,将其存储在交叉连接的派生表中(FROM子句中的子查询):

SELECT t.*
FROM my_table t
CROSS JOIN (SELECT :Param as Param) AS x
WHERE first_name LIKE x.Param
   OR last_name  LIKE x.Param
   OR biography  LIKE x.Param
wxclj1h5

wxclj1h55#

正如其他人所指出的,有很多变通方法:
1.使用不同的占位符,同时为它们提供相同的值。
1.重写查询,以便只需要唯一的占位符。
1.将ATTR_EMULATE_PREPARES设置为true
如果上面的方法不可行也不可取,还有另一种优雅的方法来解决这个问题,通过使用SQL中的变量:

DECLARE @MyVariable AS INT = :value;
SELECT column_x FROM table WHERE column_y = @MyVariable OR column_z = @MyVariable;

然后通过赋值value来准备这个语句。

0tdrvxhp

0tdrvxhp6#

有一个解决方法:

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));
  }

总之,使用具有相同条件的不同占位符。

相关问题