2009-10-31 71 views
5

我常常解析json供稿,只需要從供稿中插入最新用戶並忽略現有用戶。SQL:僅將新行/記錄插入表中?

我想我需要的是基於某些搜索ON DUPLICATE KEY UPDATEINSERT IGNORE,但我不能肯定這就是爲什麼我要求 - 這樣的例子:

users 
1  John 
2  Bob 

部分JSON:

{ userid:1, name:'John' }, 
{ userid:2, name:'Bob' }, 
{ userid:3, name:'Jeff' } 

從這個飼料我只想插入傑夫。我可以通過所有用戶做一個簡單的循環,並做一個簡單的SELECT查詢,看看用戶ID是否已經在表中,如果沒有,我做一個INSERT,但我懷疑它不會是一個有效和實用的方法。

順便說一句,我使用Zend_Db進行數據庫交互,如果任何人想迎合特定的答案:)我不介意通用的戰略解決方案。

回答

5

ON DUPLICATE KEY UPDATE替代允許引用更新與插入決定數據庫:

INSERT INTO table (userid, name) VALUES (2, 'Bobby'); 
    ON DUPLICATE KEY UPDATE name = 'Bobby'; 

將更新名稱字段來「博比」,如果有用戶ID 2的條目已經存在。

,如果你提供一個非有效的操作,以更新您可以使用它作爲一個替代INSERT IGNORE

INSERT INTO table (userid, name) VALUES (2, 'Bobby'); 
    ON DUPLICATE KEY UPDATE name = name; 

如果用戶ID 2已經存在,從而避免其他錯誤的警告和吞嚥這將做什麼你會得到時使用INSERT IGNORE


另一種方法是REPLACE

REPLACE INTO table (userid, name) VALUES (2, 'Bobby'); 

這會做一個正常的插如果用戶標識2尚不存在。如果確實存在,它將首先刪除舊條目,然後插入一個新條目。


請注意,這兩個版本都是針對SQL的MySQL特定擴展。

0

在循環中,您可以先進行更新,如果沒有行受到影響,則表示它是新條目。跟蹤那些「失敗的更新」,然後將它們作爲新條目插入。

我不熟悉Zend_Db,但我認爲它可以返回一個更新是否影響了多少行。

+0

不知怎的,我誤解了如果找到需要更新現有用戶的問題,否則插入爲新的。呃...倒票 – 2009-10-31 11:42:19

2

您需要定義用戶ID作爲主鍵或唯一鍵,使用這樣的:如果用戶ID 2已經存在,它會忽略,並移動到下一個插入

INSERT IGNORE INTO table (userid, name) VALUES (2, 'Bob'); 

您也可以在表架構上使用ON DUPLICATE KEY UPDATE。 另一種替代方法可能是使用REPLACE INTO語法。

REPLACE INTO table (userid, name) VALUES (2, 'Bob'); 

這將嘗試插入,如果記錄已經存在,它會重新插入之前將其刪除。

+0

Zend_Db支持'INSERT IGNORE'嗎? – 2009-10-31 11:36:39

+0

老實說,NoFId。 – 2009-10-31 11:40:43

+0

'IGNORE'會導致數據庫引擎發出警告而不是錯誤,因此查詢的執行不會停止。這種方法的缺點是遇到的* any *錯誤將被忽略/轉向警告,而不僅僅是一個重複的鍵。 – 2009-10-31 11:44:00

4

對於Zend框架,我做的是插入語句的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; 
    } 
} 
+0

因爲嚴格的標準,您需要放棄$ bIgnore:Your_Model :: insert()的聲明應該與...中的Zend_Db_Table_Abstract :: insert(array $ data)兼容... – bensiu 2013-10-02 19:53:46

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(); 
}