在 Yii2 中使用 plpgsql 绑定查询值

Bind values for query with plpgsql in Yii2

我用 Yii2 DAO 执行 SQL 查询。

$db->createCommand("
  DO $$
  DECLARE
    rec RECORD;
    pos INT := 0;
  BEGIN
    FOR rec IN (SELECT * FROM table1 WHERE "type" = :t LOOP
      UPDATE table1    SET position = pos    WHERE id = rec.id;
      pos := pos + 2;
    END LOOP;
  END;
  $$ language 'plpgsql'
", [':t' => 0])->execute();

但失败并出现错误:

SQLSTATE[42P18]: Indeterminate datatype: 7
ERROR:  could not determine data type of parameter 

type 列有 INT 类型。我尝试使用 [':t' => [0, \PDO::PARAM_INT]] 显式设置参数类型。但错误仍然存​​在。如果我将值直接连接到 SQL 字符串中,它会起作用,但这不是解决方案。 :t 只是该查询中的一个参数。

其他简单的 SQL 查询成功。此问题仅存在于带有过程的查询中。如果我 运行 来自 DataGrip 的这个查询,它就有效。但是在 PHP 它失败了。

为什么它不起作用,我如何为此类查询绑定参数?

如果您 create an actual function 并调用它,您可以传递 values 作为参数。

但是当您执行 DO statement 时,函数体(在您的示例中包含在美元引号 $$ 中)只是一个 字符串文字 。没有参数传递,也没有返回任何内容。您必须 将值作为字符串连接 到 plpgsql 代码中。

但你也不需要。请改用简单的 准备好的语句 。无论如何比循环便宜得多:

UPDATE table1 t
SET    position = t1.pos
FROM  (
   SELECT id, (row_number() OVER () - 1) * 2 AS pos 
   FROM   table1
   WHERE  "type" = :t
   ) t1
WHERE  t.id = t1.id

现在传递参数值很简单。

旁白:结果是任意的,除非您将 ORDER BY 添加到 OVER 子句。你原来也有这个弱点。

相关:

  • What are '$$' used for in PL/pgSQL