我想在Zend Framework 1.5中使用ON DUPLICATE KEY UPDATE
,这是可能的吗?
示例
INSERT INTO sometable (...)
VALUES (...)
ON DUPLICATE KEY UPDATE ...
我想在Zend Framework 1.5中使用ON DUPLICATE KEY UPDATE
,这是可能的吗?
示例
INSERT INTO sometable (...)
VALUES (...)
ON DUPLICATE KEY UPDATE ...
我曾在Zend工作,专门从事Zend_Db的工作。
不,没有针对ON DUPLICATE KEY UPDATE
语法的API支持。 对于这种情况,您必须使用query()
并自己形成完整的SQL语句。
我不建议像harvejs展示的那样将值插入SQL中。 请使用查询参数。
编辑:您可以使用VALUES()
表达式避免重复参数。
$sql = "INSERT INTO sometable (id, col2, col3) VALUES (:id, :col2, :col3)
ON DUPLICATE KEY UPDATE col2 = VALUES(col2), col3 = VALUES(col3)";
$values = array("id"=>1, "col2"=>327, "col3"=>"active");
VALUES()
简化ON DUPLICATE KEY UPDATE
子句并减少脚本需要处理的数量:$sql = 'INSERT INTO ... ON DUPLICATE KEY UPDATE id = VALUES(id), col2 = VALUES(col2), col3 = VALUES(col3)';
@Bill Karwin: 很棒的解决方案!但是如果使用命名占位符(“:id”,“:col1”等)而不是问号,那就更好了。这样您就不需要通过array_marge来重复值。此外,如果使用“INSERT”的“SET”语法而不是“VALUES”,则代码更容易自动生成任何字段集。
$sql = 'INSERT INTO sometable SET id = :id, col2 = :col2, col3 = :col3
ON DUPLICATE KEY UPDATE id = :id, col2 = :col2, col3 = :col3';
$arrayData = array('column1' => value1, 'column2' => value2, ...)
class Model_Db_Abstract extends Zend_Db_Table_Abstract
{
protected $_name;
protected $_primaryKey;
public function insertOrUpdate($arrayData)
{
$query = 'INSERT INTO `'. $this->_name.'` ('.implode(',',array_keys($arrayData)).') VALUES ('.implode(',',array_fill(1, count($arrayData), '?')).') ON DUPLICATE KEY UPDATE '.implode(' = ?,',array_keys($arrayData)).' = ?';
return $this->getAdapter()->query($query,array_merge(array_values($arrayData),array_values($arrayData)));
}
}
用法:
例如:Model_Db_Contractors.php
class Model_Db_Contractors extends Model_Db_Abstract
{
protected $_name = 'contractors';
protected $_primaryKey = 'contractor_id';
...
}
IndexController.php
class IndexController extends Zend_Controller_Action
{
public function saveAction()
{
$contractorModel = new Model_Db_Contractors();
$aPost = $this->getRequest()->getPost();
/* some filtering, checking, etc */
$contractorModel->insertOrUpdate($aPost);
}
}
array_merge(array_values($arrayData),array_values($arrayData))
,但是 array_values($arrayData)
就足够了。 - PatrioticcowREPLACE INTO sometable SET field ='value'.....
如果存在则更新,否则插入。这是标准mysql api的一部分。
REPLACE
会删除任何匹配的现有行并插入一个新行。如果您没有插入所有值,这将导致不良行为。例如:您有一个带有 time_created
的表。如果您使用 UPDATE
而没有设置值,它将保持与创建该行时相同。如果您使用 REPLACE
,则该行将被删除,一个新行将被插入,并且 time_created
将被设置为当前时间。 - apfelbox更新Pawel的答案以支持单独的插入和更新数据,并且支持Zend Db表达式
class Model_Db_Abstract extends Zend_Db_Table_Abstract
{
protected $_name;
protected $_primaryKey;
public function insertOrUpdate($arrayData)
{
$insertDataValuesForQuery = [];
$queryParams = [];
foreach ($insertData as $key => $value) {
if (gettype($value) == "object") {
array_push($insertDataValuesForQuery, $value->__toString());
continue;
}
array_push($insertDataValuesForQuery, "?");
array_push($queryParams, $value);
}
$updateDataValuesForQuery = [];
foreach ($updateData as $key => $value) {
if (gettype($value) == "object") {
array_push($updateDataValuesForQuery, $key . " = " . $value->__toString());
continue;
}
array_push($updateDataValuesForQuery, $key . " = ?");
array_push($queryParams, $value);
}
$query = 'INSERT INTO ' . $this->_name . ' (' . implode(',', array_keys($insertData)) . ') VALUES (' . implode(',', $insertDataValuesForQuery) . ') ON DUPLICATE KEY UPDATE ' . implode(' , ', $updateDataValuesForQuery);
return $this->getAdapter()->query($query, $queryParams);
}
}
你可以简单地这样做:
在你的id上设置唯一索引
然后
try {
do insert here
} catch (Exception $e) {
do update here
}