如何防止 PDO 将问号解释为占位符?

Posted

技术标签:

【中文标题】如何防止 PDO 将问号解释为占位符?【英文标题】:How to prevent PDO from interpreting a question mark as a placeholder? 【发布时间】:2013-04-25 02:01:37 【问题描述】:

为了检测hstore 中是否存在键,我需要运行如下查询:

SELECT * FROM tbl WHERE hst ? 'foo'

但是,这给了我一个 PDOException:

PDOException: SQLSTATE[HY093]: Invalid parameter number: no parameters were bound: SELECT * FROM tbl WHERE hst ? 'foo'

有什么办法可以避开问号,这样 PDO 就不会把它当作占位符了?我尝试了最多四个反斜杠和一个双问号 (??),但似乎没有什么能说服 PDO 不理会问号。

【问题讨论】:

【参考方案1】:

使用函数调用形式。根据系统目录,hstore ? 算子使用了exist 函数:

regress=# select oprname, oprcode from pg_operator where oprname = '?';
 oprname | oprcode 
---------+---------
 ?       | exist
(1 row)

所以你可以写:

SELECT * FROM tbl WHERE exist(hst,'foo');

(我个人不是 hstore 以操作员为中心的设计和文档的忠实粉丝,我认为它丢弃了基于函数的接口的有用的自文档属性而没有任何真正的好处,我通常使用它的函数调用而不是它的运算符。仅仅因为你可以定义运算符并不意味着你应该。)

【讨论】:

我现在正在使用它,但不幸的是没有函数替换 ?& 和 ?|运营商。我想我可以自己写……糟透了。 嗯?必须有一个函数支持任何运算符。果然,把它们插到上面,?&就是exists_all?|就是exists_any ? 运算符替换为与JSONB 数据类型一起使用时,将EXIST() 替换为JSONB_EXISTS()【参考方案2】:

我在搜索 JSONB 数据时遇到了同样的问题。完整的问题是here

SELECT * FROM post WHERE locations ? :location;

PostgreSQL 9.5 的解决方法类似:

SELECT * FROM post WHERE jsonb_exists(locations, :location);

我还在 php 错误跟踪系统上开了一个ticket

更新

正如 Diabl0 所提到的,建议的解决方案有效但不使用索引。 测试:

CREATE INDEX tempidxgin ON post USING GIN (locations);

【讨论】:

请不要发布所有此类问题的答案。而是将它们标记为重复。 @YourCommonSense 我提到解决方法(解决方案)是不同的,值得强调。我不知道你说的都是什么意思。它在适当的地方得到关注和定义。 这个解决方案在运行时有一个巨大的缺点 - 使用 jsonb 函数进行查询不使用可能导致性能显着下降的索引。【参考方案3】:

我建议你禁用 PDO 原生准备好的语句,这样问号就会被忽略:

$pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, true);

【讨论】:

无论你如何设置这个参数,PDO 都会做一些语句解析,并曲解? 这个答案对我有用,尽管它不适用于我之前使用的 PHP 版本。试图将 downvote 更改为 upvote,除非您修改,否则不会让我;)

以上是关于如何防止 PDO 将问号解释为占位符?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 PDO 不允许具有相同名称的多个占位符?

MySQL 返回 PDO 占位符名称

MySQL 返回 PDO 占位符名称

Python sqlite3 占位符

在 PDO 中的执行函数中将 NULL 值绑定到具有关联数组的命名占位符的问题

JDBC中?占位符的使用说明