【问题标题】:Bind values for query with plpgsql in Yii2在 Yii2 中使用 plpgsql 绑定查询值
【发布时间】:2017-10-23 09:44:43
【问题描述】:

我使用 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 $1

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

其他简单的 SQL 查询也能成功运行。此问题仅存在于带有过程的查询。如果我从 DataGrip 运行这个查询,它就可以工作。但在 PHP 中它失败了。

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

【问题讨论】:

    标签: php postgresql pdo yii2 plpgsql


    【解决方案1】:

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

    但是当您执行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 子句中。你的原作也有这个弱点。

    相关:

    【讨论】:

    • 感谢您的完整解释!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-23
    • 1970-01-01
    • 2022-01-09
    • 1970-01-01
    • 2021-05-27
    相关资源
    最近更新 更多