【问题标题】:In PHP PDO how to get "RETURNING" clause values of PostgreSQL upsert query在 PHP PDO 中如何获取 PostgreSQL upsert 查询的“RETURNING”子句值
【发布时间】:2021-03-25 04:40:53
【问题描述】:

我有这个用 postgreSQL 编写的 upsert 查询

$statement = 'INSERT INTO "CharactersUnlockToBuyLevels"
                ("CharacterId", "LevelId", "AmountToBuy", "EagleStatueId", "Location", 
                 "MapCoordinateTop", "MapCoordinateLeft")
              VALUES 
                (:CharacterId, :LevelId, :AmountToBuy, :EagleStatueId, :Location, 
                 :MapCoordinateTop, :MapCoordinateLeft)
              ON CONFLICT
                ("CharacterId")
              DO UPDATE 
                SET 
                  "LevelId" = EXCLUDED."LevelId",
                  "AmountToBuy" = EXCLUDED."AmountToBuy",
                  "EagleStatueId" = EXCLUDED."EagleStatueId",
                  "Location" = EXCLUDED."Location",
                  "MapCoordinateTop" = EXCLUDED."MapCoordinateTop",
                  "MapCoordinateLeft" = EXCLUDED."MapCoordinateLeft"                            
              RETURNING "CharacterUnlockToBuyLevelId"
             ';

查询工作正常,如果我在 PgAdmin 中运行它,我会按预期返回“CharacterUnlockToBuyLevelId”。但是,如果我准备它并使用 PHP 的 PDO 执行它,那么我似乎无法取回 RETURNING 值。

$stmt = $this->db->prepare($statement);
$returnedId = $stmt->execute(array(
     'CharacterId' => $characterId,
     'LevelId' => $unlockMethod['LevelId'],
     'AmountToBuy' => $unlockMethod['AmountToBuy'],
     'EagleStatueId' => $unlockMethod['EagleStatueId'],
     'Location' => $unlockMethod['Location'],
     'MapCoordinateTop' => $unlockMethod['MapCoordinateTop'],
     'MapCoordinateLeft' => $unlockMethod['MapCoordinateLeft'],
));

这只是返回true,所以$returnedId实际上不会保存id,而只是值true。如何使用 PDO 的预处理语句从 upsert 查询中获取返回值?

【问题讨论】:

  • 你试过with i as (. . . ) select i.* from i吗?
  • 这可以工作,但我想保持我的查询尽可能干净,而不是围绕它构建额外的,只是为了得到一个已经返回的值,并且正在寻找 PHP 中的解决方案PDO
  • 。 .我注意到查询返回一列,但您似乎正在阅读其中的许多。
  • 我不明白您的最后一条评论,它要么更新现有记录,要么插入新记录。我只需要知道更新/插入记录的主键“CharacterUnlockToBuyLevelId”,这就是我要返回的内容
  • 。 .结果集中只返回RETURNING 子句中的列。

标签: php postgresql pdo


【解决方案1】:

来自http://php.net/manual/en/pdostatement.execute.php

public bool PDOStatement::execute ([ 数组 $input_parameters ] )

要获得返回值,请尝试fetchAll

$stmt = $this->db->prepare($statement);
$returnedId = $stmt->execute(array(
     'CharacterId' => $characterId,
     'LevelId' => $unlockMethod['LevelId'],
     'AmountToBuy' => $unlockMethod['AmountToBuy'],
     'EagleStatueId' => $unlockMethod['EagleStatueId'],
     'Location' => $unlockMethod['Location'],
     'MapCoordinateTop' => $unlockMethod['MapCoordinateTop'],
     'MapCoordinateLeft' => $unlockMethod['MapCoordinateLeft'],
));
$yourVal=$stmt->fetchAll();

【讨论】:

  • 谢谢Vao,我希望在一次调用数据库中就可以得到它,而不是事后去获取它,但我想那是不可能的。因为我知道我只用一个值返回一行,所以我使用 fetchColumn() 代替。这会立即给我 id 编号,避免我不得不将其从 fetchAll() 或 fetch() 将返回的数组中取出
【解决方案2】:

如果您准备扩展 PDOStatement 类,您可以稍微简化一下流程。诀窍是将fetchAll 包装在execute 方法的扩展版本中。

因为PDOStatement是间接生成的,所以你首先需要告诉PDO使用你的扩展版本,而不是标准版本:

$pdo=new PDO($dsn,$user,$password) or die('oops');
$pdo->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('DBStatement',array($pdo)));

...其中DBStatement 将是您的扩展PDOStatement

然后您可以按如下方式扩展该类:

class DBStatement extends PDOStatement {
    public $pdo;
    protected function __construct($pdo) {
        $this->pdo = $pdo;
    }
    function executeReturning($data=null) {
        parent::execute($data);
        return $this->fetchAll();
    }
}

第一部分是让您的新课程以与原课程相同的方式开始所必需的。第二部分执行语句,然后返回结果。

你可以这样称呼它:

$sql='INSERT INTO testing(data) VALUES(?) RETURNING id,data';
$pds=$pdo->prepare($sql);
print_r($pds->executeReturning(['this space for rent']));

【讨论】:

    猜你喜欢
    • 2014-12-13
    • 2015-11-09
    • 2011-01-09
    • 2011-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-14
    相关资源
    最近更新 更多