![](/img/trans.png)
[英]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.