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

mik*_*ikl 20 php postgresql pdo

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

SELECT * FROM tbl WHERE hst ? 'foo'
Run Code Online (Sandbox Code Playgroud)

但是,这给了我一个PDOException:

PDOException: SQLSTATE[HY093]: Invalid parameter number: no parameters were bound: SELECT * FROM tbl WHERE hst ? 'foo'
Run Code Online (Sandbox Code Playgroud)

有没有办法逃避问号,所以PDO不会把它作为占位符拿起来?我尝试过多达四个反斜杠,以及一个双问号(??),但似乎没有任何说服PDO单独留下问号.

Cra*_*ger 31

使用函数调用表单.根据系统目录,hstore ?运算符使用以下exist函数:

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

所以你可以写:

SELECT * FROM tbl WHERE exist(hst,'foo');
Run Code Online (Sandbox Code Playgroud)

(就个人而言,我不是hstore以运营商为中心的设计和文档的忠实粉丝,我认为它丢弃了基于函数的界面的有用的自我文档属性而没有任何实际好处,我通常使用它的函数调用而不是它的运算符.因为你可以定义运算符并不意味着你应该.)

  • 替换`?`运算符以使用JSONB数据类型时,将`EXIST()`替换为`JSONB_EXISTS()`. (4认同)
  • 嗯?必须有一个支持任何操作员的功能.果然,将它们插入上面,`?&`是`exists_all`,`?|`是`exists_any`. (3认同)

mic*_*lbn 10

我在搜索JSONB数据时遇到了同样的问题.完整的问题在这里

SELECT * FROM post WHERE locations ? :location;
Run Code Online (Sandbox Code Playgroud)

解决方法PostgreSQL 9.5类似:

SELECT * FROM post WHERE jsonb_exists(locations, :location);
Run Code Online (Sandbox Code Playgroud)

我还在PHP bug跟踪系统上打开了一张票

更新

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

CREATE INDEX tempidxgin ON post USING GIN (locations);
Run Code Online (Sandbox Code Playgroud)

  • 这个解决方案工作有一个巨大的缺点 - 使用jsonb函数查询不使用可能导致显着性能降级的索引. (3认同)