【问题标题】:PDO Parameterized Query - Reuse named placeholders?PDO 参数化查询 - 重用命名占位符?
【发布时间】:2011-01-26 18:53:56
【问题描述】:

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

【问题讨论】:

  • 你为什么不试试呢? PDO::prepare 说是,PDOStatement::execute 说您可能需要关闭依赖于驱动程序的数据库游标。
  • 我试过了,我一直收到错误,但我认为我做错了什么。在文档中找不到任何内容(正在查看 PDO::bindParam)。在 PDO::prepare 中找到它,感谢您为我指明正确的方向!
  • 其实第一部分SELECT :Param那是不可能的;你不能绑定表/列,请咨询stackoverflow.com/q/182287但是, 你可以这样做$Param = "column"; SELECT $Param...
  • 你认为你可以用这个答案来奖励我吗?当前接受的状态是不可能的,但这是我的解决方案

标签: php pdo


【解决方案1】:

PDO::prepare 声明“您不能在准备好的语句中两次使用同名的命名参数标记”,所以我想那是不可以的。

【讨论】:

  • 文档并不完全正确。如果PDO::ATTR_EMULATE_PREPAREStrue,PDO DOES 支持重用命名参数标记。
  • 好像有人更新了文档。它现在说“你不能在准备好的语句中多次使用同名的命名参数标记,除非仿真模式打开。”
  • 你说对了一部分。但是SELECT :Param 是不可能的,因为您不能绑定表/列。查看stackoverflow.com/q/182287
  • 但是如果你使用PDO::ATTR_EMULATE_PREPARES,pdo 会把所有的东西都变成一个字符串
【解决方案2】:

你可以设置PDO::ATTR_EMULATE_PREPARES = true

例如$connection->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);.

如果你使用 Laravel,你可以在 config/database.phpoptions 数组中设置它。例如PDO::ATTR_EMULATE_PREPARES => true

【讨论】:

    【解决方案3】:

    除了重用之外,这里的主要问题是您正在尝试动态更改 col 名称。

    此答案由匿名用户在http://php.net/manual/en/pdo.prepare.php 上发布:

    对于那些想知道为什么在占位符周围添加引号是错误的, 以及为什么不能为表名或列名使用占位符:

    对于如何准备占位符有一个常见的误解 语句有效:它们不是简单地替换为 as (转义) 字符串,并执行生成的 SQL。相反,DBMS 要求 “准备”一个语句提出了一个完整的查询计划,说明它是如何实现的 将执行该查询,包括它将执行哪些表和索引 使用,不管你怎么填,都是一样的 占位符。

    “SELECT name FROM my_table WHERE id = :value”的计划将是 用 ":value" 替换什么都一样,但看起来很相似 “SELECT name FROM :table WHERE id = :value”无法计划,因为 DBMS 不知道您实际上要从哪个表中选择。

    即使使用“模拟准备”,PDO 也不能让您使用 任何地方的占位符,因为它必须解决你的问题 意思是:“Select :foo From some_table”是否意味着“:foo”将是一个 列引用,还是文字字符串?

    当您的查询使用动态列引用时,您应该明确地将您知道存在于表中的列列入白名单,例如使用在 default: 子句中抛出异常的 switch 语句。

    【讨论】:

      【解决方案4】:

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

      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
      

      【讨论】:

        猜你喜欢
        • 2013-10-03
        • 2012-05-23
        • 2016-10-17
        • 1970-01-01
        • 2012-11-20
        • 1970-01-01
        相关资源
        最近更新 更多