在PostgreSQL中使用PDO时如何忽略问号作为占位符

mic*_*lbn 10 php postgresql pdo

注意:

该问题可视为本课题的副本.它确实指出了与PDO相同的问题.但它的解决方案解决方案有点不同,因为目标不同.我将在那里发布JSONB的解决方法和PHP票证的链接.

当我准备以下查询时:

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

发生以下警告:

警告:PDO :: prepare():SQLSTATE [HY093]:参数号无效:在xx行的/path/file.php中混合命名和位置参数

问号是一个有效的PostgreSQL运算符,但PDO将其视为占位符.

是否有一种正确的方法来配置PDO以忽略问号作为占位符?

我会发布一个下面的解决方法.希望有更好的方法

编辑 我在PHP bug跟踪系统中添加了一个票证

Jul*_*tré 6

从 PHP 7.4 开始,支持转义问号

\n
\n

(...) 问号可以通过加倍 (...) 来转义。这意味着当将查询发送到数据库时,\xe2\x80\x9c??\xe2\x80\x9d 字符串将被转换为 \xe2\x80\x9c?\xe2\x80\x9d,而 \xe2\x80\ x9c?\xe2\x80\x9d 仍将被解释为位置参数占位符。

\n
\n

在您的示例中,您可以使用:

\n
$sql = "SELECT * FROM post WHERE locations ?? :location;";\n
Run Code Online (Sandbox Code Playgroud)\n


mic*_*lbn 5

这是我的问题的解决方法.它通过使用PostgreSQL函数来替换?运算符来解决问题.

我真的不喜欢它,因为它不会使PDO更符合PostgreSQL.但我发现没有真正的解决方案.

CREATE FUNCTION json_key_exists(JSONB,TEXT) RETURNS BOOLEAN LANGUAGE SQL STABLE AS $f$
    SELECT $1 ? $2
$f$;
Run Code Online (Sandbox Code Playgroud)

现在我可以使用查询:

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

来自freenode #postgresql的神话般的RhodiumToad提出了解决方法

编辑

正如@Abelisto建议的那样,没有必要像jsonb_exists(jsonb, text)avialabe 一样创建上面的函数

  • 您可以在psql中探索`?`运算符定义(`\ do +"?"`)并找出它使用函数`jsonb_exists(jsonb,text)`作为其背景.所以你不需要定义你的函数,但重用已经存在的函数. (2认同)
  • 我想建议在里面使用带有`?`的自定义不可变函数,因为**jsonb_exists()不可索引,而`?`是**.请参阅https://dba.stackexchange.com/questions/90002/postgresql-operator-uses-index-but-underlying-function-does-not (2认同)