In PHP PDO how to get “RETURNING” clause values of PostgreSQL upsert query

时光总嘲笑我的痴心妄想 提交于 2021-02-05 07:22:05

问题


I have this upsert query written in postgreSQL

$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"
             ';

The query works fine, and if I run it in PgAdmin, I get the "CharacterUnlockToBuyLevelId" back as expected. However if I prepare it and execute it using PHP's PDO then I can't seem to get the RETURNING value back.

$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'],
));

This just returns true, so $returnedId will not actually hold the id but just the value true. How can I get the RETURNING value from the upsert query back with PDO's prepared statements?


回答1:


from http://php.net/manual/en/pdostatement.execute.php:

public bool PDOStatement::execute ([ array $input_parameters ] )

to get returned val, try 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();



回答2:


If you’re prepared to extend the PDOStatement class, you can simplify the process a little. The trick is to wrap the fetchAll inside your extended version of the execute method.

Because the PDOStatement is generated indirectly, you first need to tell PDO to use your extended version, rather than the standard version:

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

… where DBStatement will be your extended PDOStatement.

You can then extend the class as follows:

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

The first part is required to get your new class to start off the same as the original. The second part executes the statement, and then returns the result.

You can then call it as follows:

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


来源:https://stackoverflow.com/questions/41077901/in-php-pdo-how-to-get-returning-clause-values-of-postgresql-upsert-query

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!