问题
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