我正在定期解析json feed,只需要插入feed中的最新用户并忽略现有用户。
根据一些搜索,我认为我需要的是ON DUPLICATE KEY UPDATE
或INSERT IGNORE
,但我不太确定我问的是什么原因 - 例如:
users
1 John
2 Bob
部分JSON:
{ userid:1, name:'John' },
{ userid:2, name:'Bob' },
{ userid:3, name:'Jeff' }
从这个Feed中我只想插入Jeff。我可以通过所有用户做一个简单的循环,并做一个简单的SELECT查询,看看用户id是否已经在表中,如果不是我做INSERT,但我怀疑它不是一个有效和实用的方法。
顺便说一下,如果有人愿意提供具体的答案,我正在使用Zend_Db进行数据库交互:)我不介意一般的战略解决方案。
答案 0 :(得分:5)
ON DUPLICATE KEY UPDATE
替代方案允许您将更新与插入决策引用到数据库:
INSERT INTO table (userid, name) VALUES (2, 'Bobby');
ON DUPLICATE KEY UPDATE name = 'Bobby';
如果已存在具有用户标识2的条目,则会将名称字段更新为“Bobby”。
如果您向UPDATE提供无效操作,则可以将其用作INSERT IGNORE
的替代方法:
INSERT INTO table (userid, name) VALUES (2, 'Bobby');
ON DUPLICATE KEY UPDATE name = name;
如果用户标识2已存在,则无效,从而避免了警告和吞下使用INSERT IGNORE
时出现的其他错误。
另一种选择是REPLACE
:
REPLACE INTO table (userid, name) VALUES (2, 'Bobby');
如果用户标识2尚不存在,这将执行正常插入。如果它确实存在,它将首先删除旧条目,然后插入一个新条目。
请注意,这两个版本都是SQL的MySQL特定扩展。
答案 1 :(得分:4)
对于Zend Framework,我所做的是insert语句的try / catch,并根据异常代码采取进一步的操作:
class Application_Model_DbTable_MyModel extends Zend_Db_Table_Abstract
public function insert($aData, $bIgnore = false)
{
try
{
$id = parent::insert($aData);
}
catch(Zend_Db_Statement_Mysqli_Exception $e)
{
// code 1062: Mysqli statement execute error : Duplicate entry
if($bIgnore && $e->getCode() == 1062)
{
// continue;
}
else
{
throw $e;
}
}
return !empty($id) ? $id : false;
}
}
答案 2 :(得分:2)
您需要将userid定义为PRIMARY或UNIQUE键,并使用类似:
的内容INSERT IGNORE INTO table (userid, name) VALUES (2, 'Bob');
如果用户ID 2已经存在,它将忽略并继续下一个插入。
您还可以在表架构上使用ON DUPLICATE KEY UPDATE。 另一种选择可能是使用REPLACE INTO语法。
REPLACE INTO table (userid, name) VALUES (2, 'Bob');
这将尝试INSERT,如果记录已经存在,它将在再次插入之前删除它。
答案 3 :(得分:1)
我的解决方案:
/**
* Perform an insert with the IGNORE word
*
* @param $data array
* @return number the number of rows affected
*/
public function insertIgnore(array $data)
{
// Start of query
$sql = sprintf("INSERT IGNORE INTO %s (", $this->getAdapter()->quoteIdentifier($this->info('name')));
// Retrieve column identifiers
$identifiers = array_keys($data);
foreach ($identifiers as $key => $value) {
// Quote identifier
$identifiers[$key] = $this->getAdapter()->quoteIdentifier($value);
}
// Concat column identifiers
$sql .= implode(', ', $identifiers);
$sql .= ") VALUES (";
foreach ($data as $key => $value) {
// Quote values
$data[$key] = $this->getAdapter()->quote($value);
}
// Concat values identifiers
$sql .= implode(', ', $data);
$sql .= ")";
// Process the query
return $this->getAdapter()->query($sql)->rowCount();
}
答案 4 :(得分:0)
在循环中,如果没有行受影响,您可以先进行更新,这意味着它是一个新条目。跟踪那些“失败的更新”,然后将它们作为新条目插入。
我不熟悉Zend_Db,但我认为它可以返回更新是否会影响行数。