12

...或问号问题。

我目前正在使用新的 jsonb 类型在 php 中实现 postgres 数据库的搜索功能。

为了实现这一点,我正在使用命名占位符执行准备好的语句。

但是,在尝试使用一些新的 postgres JSON 包含和存在运算符以及命名占位符时,我遇到了一个有趣的问题。

问题的基础是运算符本身使用问号?作为其语法的一部分。IE

?JSON 值中是否存在键/元素字符串?

?|这些键/元素字符串是否存在?

?&所有这些键/元素字符串都存在吗?

这意味着我在 PHP 中有类似这样的语句。

$sth = $dbh->prepare("SELECT * FROM stuff WHERE meta ? :value");
$sth->bindValue(1, $value, PDO::PARAM_STR);
$sth->execute();

这失败了,因为问号被解释为占位符。为了解决这个问题,我试图让操作符本身成为一个命名参数,就像这样。

$sth = $dbh->prepare("SELECT * FROM stuff WHERE meta :operator :value");
$sth->bindValue(1, $operator, PDO::PARAM_STR);
$sth->bindValue(2, $value, PDO::PARAM_STR);
$sth->execute();

然而,这只会引发与使用裸运算符相同的错误,即

ERROR: syntax error at or near \"$1\"1

有没有其他人遇到过这个问题,或者有人能想到一个好的解决方法吗?

有没有办法转义或传递问号,以便可以将 postgres jsonb 包含和存在运算符与 PDO 参数化查询一起使用?

4

1 回答 1

21

您可以使用相应的函数代替运算符(jsonb_exists、jsonb_exists_any、jsonb_exists_all)。例如\do+ "?"在 psql 中运行以查看函数名称?操作员。

或者定义你自己的不带“?”的运算符 符号代替。

例如:

CREATE OPERATOR ~@ (LEFTARG = jsonb, RIGHTARG = text, PROCEDURE = jsonb_exists)    
CREATE OPERATOR ~@| (LEFTARG = jsonb, RIGHTARG = text[], PROCEDURE = jsonb_exists_any)
CREATE OPERATOR ~@& (LEFTARG = jsonb, RIGHTARG = text[], PROCEDURE = jsonb_exists_all)  

这样人们就可以分别使用~@,代替,~@|和。例如~@&??|?&

$sth = $dbh->prepare("SELECT * FROM stuff WHERE meta ~@ :value");
$sth->bindValue(1, $value, PDO::PARAM_STR);
$sth->execute();
于 2015-05-26T17:19:12.163 回答