2009-10-31 14 views
5

Bir json özet akışını rutin olarak ayrıştırıyorum ve yalnızca en yeni kullanıcıları beslemeden ekleyip mevcut kullanıcıları yok saymalıyım.SQL: Sadece yeni satırları/kayıtları bir tabloya ekle?

Sanırım biraz taramasına dayalı ON DUPLICATE KEY UPDATE veya INSERT IGNORE ihtiyacımız olan şey düşünmek ama yüzden soruyorum hangi oldukça emin değilim - örneğin bu yüzden:

users 
1  John 
2  Bob 

Kısmi JSON:

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

Bu beslemeden sadece Jeff eklemek istiyorum. Tüm kullanıcılar arasında basit bir döngü yapabilir ve basit bir SELECT sorgusu yapabilir ve kullanıcı kimliğinin zaten bir tabloda bulunup bulunmadığını görürsem, bir INSERT yapmazsam, bunun verimli ve pratik bir yöntem olmayacağından şüphelenirim. Bu arada, belirli bir cevabı almak isteyen herkesin veritabanı etkileşimi için Zend_Db kullanıyorum :) Yine de genel bir stratejik çözüm umurumda değil.

cevap

5

ON DUPLICATE KEY UPDATE alternatif veritabanına ekleme kararı vs güncelleştirmeyi başvurmak sağlar: klnckimliği 2 ile giriş zaten varsa

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

, adı alanını etmek 'Bobby' güncelliyorduk.

Eğer UPDATE bir etkin olmayan operasyonu tedarik eğer INSERT IGNORE alternatif olarak kullanabilirsiniz

:

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

kimliği 2 zaten böylece diğer hataların uyarı ve yutma kaçınarak, varsa bu hiçbir şey yapacağını INSERT IGNORE kullanırken alırsınız.


diğer alternatif REPLACE olacaktır: kimliği 2 henüz yoksa

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

Bu normal ekleme yapmak istiyorum. Varsa, önce eski girişi siler ve ardından yeni bir tane ekler.


Her iki sürümün de SQL'e özgü MySQL uzantıları olduğunu unutmayın.

Zend Framework için
0

Döngüde, önce bir güncelleştirme yapabilirsiniz, hiçbir satır etkilenmezse, yeni bir girdi demektir. Bu 'başarısız güncellemeler' takip edin ve daha sonra yeni girişler olarak bir giriş yapın.

Zend_Db'ye aşina değilim ama bir güncelleştirmenin kaç satır (lar) etkileyip etkilemediğini döndürebileceğini varsayalım. Userid 2 zaten görmezden ve sonraki ekleme için hareket edecek varsa

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

:

+0

Bir şekilde yanlış okumak Varsa, mevcut kullanıcıları güncellemeye gerek olup olmadığı sorulur, aksi halde yeni olarak eklenir. iyi ... down-vote –

2

Bir İLKÖĞRETİM veya EŞSİZ anahtar olarak kimliği tanımlamak ve böyle bir şey kullanmak gerekir.

Ayrıca, tablo şemasındaki DUPLICATE KEY UPDATE öğelerini de kullanabilirsiniz. Başka bir alternatif, REPLACE INTO sözdizimini kullanmak olabilir.

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

Bu kayıt zaten tekrar takmadan önce SİLER varsa, INSERT çalışacaktır.

+0

Zend_Db'de 'INSERT IGNORE' destekleniyor mu? –

+0

Dürüst, NoFId. –

+0

'IGNORE', db motorunun hata yerine uyarı vermesine neden olacak, dolayısıyla sorgunun yürütülmesi durdurulmayacaktır. Bu yaklaşımın bir dezavantajı, * herhangi bir * hatayla karşılaşıldığının, sadece bir kopya anahtarı değil, ihbar/ihmal edileceğidir. –

4

, ne yapmam insert ifadesinin bir deneme/yakalama ve istisna koduna dayalı gerekli işlemleri gerçekleştirir:

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

Strict Standards nedeniyle $ bIgnore vermeniz gerekiyor: Your_Model :: insert() öğesi, Zend_Db_Table_Abstract :: insert (array $ data) ile uyumlu olmalıdır ... – bensiu

1

Çözümümün:

/** 
* 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(); 
} 
İlgili konular