[英]MySQL syntax to insert new rows based on mixed variables plus select records from another table
[英]SQL: Insert only new rows/records into a table?
我正在定期解析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' }
从这个饲料我只想插入杰夫。 我可以通过所有用户做一个简单的循环,并做一个简单的SELECT查询,看看用户id是否已经在表中,如果不是我做INSERT,但我怀疑它不是一个有效和实用的方法。
顺便说一句,如果有人愿意提供具体的答案,我正在使用Zend_Db进行数据库交互:)我不介意一般的战略解决方案。
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的扩展。
对于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;
}
}
您需要将userid定义为PRIMARY或UNIQUE键,并使用以下内容:
INSERT IGNORE INTO table (userid, name) VALUES (2, 'Bob');
如果用户标识2已经存在,它将忽略并继续下一个插入。
您还可以在表模式上使用ON DUPLICATE KEY UPDATE。 另一种替代方法可能是使用REPLACE INTO语法。
REPLACE INTO table (userid, name) VALUES (2, 'Bob');
这将尝试INSERT,如果记录已经存在,它将在再次INSERT之前删除它。
我的解决方案
/**
* 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();
}
在循环中,如果没有行受影响,您可以先进行更新,这意味着它是一个新条目。 跟踪那些“失败的更新”,然后将它们作为新条目插入。
我不熟悉Zend_Db,但我认为它可以返回更新是否影响了多少行。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.