INSERT SET:如果行不存在则为id,UPDATE WHERE:否则为id

时间:2013-06-23 16:04:44

标签: php mysql

我有一个代码,如果它不存在,则在数据库中创建一个具有指定id的行,否则更新该行。它有点慢(它检查是否存在行然后插入/更新它)并且我想要优化它。如何将整个事物合并到一个SQL查询中?我想我应该使用INSERT ... ON DUPLICATE KEY UPDATE但我不明白它是如何工作的。谢谢。

$objectExists = true;
try {
    $object = new Object();
    $object->loadFromDatabaseById($this->id, $dbh); // tries to load object from database, throws
                                         // ExceptionNotFound if object with specified id does not exist
}
catch(ExceptionNotFound $e) {
    $objectExists = false;
}

if($objectExists)
    $sth = $dbh->prepare(
        'UPDATE objects ' .
        'SET property1 = :property1, ' .
            'property2 = :property2, ' .
            'property3 = :property3 ' .
        'WHERE id = :id'
    );
else
    $sth = $dbh->prepare(
        'INSERT INTO objects ' .
        'SET id = :id, ' .
            'property1 = :property1, ' .
            'property2 = :property2, ' .
            'property3 = :property3'
    );
$sth->bindParam(':id', $this->id, \PDO::PARAM_INT);
$sth->bindParam(':property1', $this->property1, \PDO::PARAM_STR);
$sth->bindParam(':property2', $this->property2, \PDO::PARAM_STR);
$sth->bindParam(':property3', $this->property3, \PDO::PARAM_INT);
$sth->execute();
$this->id = (int)$this->id;

2 个答案:

答案 0 :(得分:1)

MySQL has a REPLACE statement完全符合您的要求:

  

REPLACEINSERT完全相同,只是如果表中的旧行与PRIMARY KEYUNIQUE索引的新行具有相同的值,在插入新行之前删除旧行。

没有删除的替代方案是INSERT ... ON DUPLICATE KEY UPDATE statement

  

如果指定ON DUPLICATE KEY UPDATE,并且插入的行会导致UNIQUE索引或PRIMARY KEY中的重复值,则MySQL会执行旧行的UPDATE

答案 1 :(得分:1)

只要id是主键或唯一键/索引,您就可以将其缩短为 -

$sth = $dbh->prepare(
    'INSERT INTO objects ( id, property1, property2, property3) ' .
    'VALUES ( :id,:property1,:property2,:property3) '. 
    'ON DUPLICATE KEY UPDATE ' .
        'property1 = :property1, ' .
        'property2 = :property2, ' .
        'property3 = :property3 '
);
$sth->bindParam(':id', $this->id, \PDO::PARAM_INT);
$sth->bindParam(':property1', $this->property1, \PDO::PARAM_STR);
$sth->bindParam(':property2', $this->property2, \PDO::PARAM_STR);
$sth->bindParam(':property3', $this->property3, \PDO::PARAM_INT);
$sth->execute();
$this->id = (int)$this->id;