2009-10-31 5 views
5

json 피드를 정기적으로 구문 분석 중이므로 피드에서 가장 새로운 사용자 만 삽입하고 기존 사용자는 무시해야합니다.SQL : 새 행/레코드 만 테이블에 삽입 하시겠습니까?

은 내가 몇 가지 검색을 기반으로 ON DUPLICATE KEY UPDATE 또는 INSERT IGNORE입니다 필요 생각하지만 난 부탁 해요 이유입니다 확실히 모르겠어요 - 그래서 예를 들면 :

users 
1  John 
2  Bob 

부분 JSON :

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

이 피드에서는 Jeff 만 삽입하고 싶습니다. 모든 사용자를 통해 간단한 루프를 수행하고 간단한 SELECT 쿼리를 수행하고 사용자 ID가 이미 테이블에 있는지 확인합니다. INSERT를 수행하지 않으면 효율적이고 실용적인 방법이 아닐 것으로 생각됩니다.

그런데 저는 누군가가 특정 답변을 원한다면 데이터베이스 상호 작용에 Zend_Db를 사용하고 있습니다. 저는 일반적인 전략적 솔루션에 신경 쓰지 않습니다.

답변

5

ON DUPLICATE KEY UPDATE 대안은 데이터베이스에 삽입 결정에 대 업데이트를 참조 할 수 있습니다 : 사용자 ID 2 항목이 이미 존재하는 경우

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

는 이름 필드에 '바비'를 업데이트한다.

업데이트에 noneffective 작업을 공급하는 경우가 INSERT IGNORE에 대한 대안으로 사용할 수 있습니다

:

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

사용자 ID 2가 이미 때문에 다른 오류의 경고 및 삼키는을 피할 수있는 경우는, 아무것도 할 수 없을 것입니다 INSERT IGNORE을 사용할 때 얻을 수 있습니다.


또 다른 대안은 REPLACE 것 : 사용자 ID이 아직 존재하지 않는 경우

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

이 정상적인 삽입을 할 것입니다. 존재하는 경우 이전 항목을 먼저 삭제 한 다음 새 항목을 삽입합니다.


두 버전 모두 MySQL에 대한 SQL 확장입니다.

젠드 프레임 워크에 대한
0

루프에서 영향을받지 않는 행이 없으면 먼저 업데이트를 수행하여 새로운 항목을 의미합니다. '실패한 업데이트'를 추적 한 다음 새 항목으로 삽입하십시오.

저는 Zend_Db에 익숙하지 않지만 업데이트로 얼마나 많은 행이 영향을 미치는지 여부를 반환 할 수 있다고 가정합니다. 사용자 ID 2가 이미 무시하고 다음 삽입로 이동합니다 존재하는 경우

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

:

+0

은 어떻게 든 내가이 오해를 발견 된 경우 기존 사용자를 업데이트해야하는지에 대한 질문. 그렇지 않으면 새로운 것으로 삽입하십시오. Well ... down-voted –

2

당신은 PRIMARY 또는 UNIQUE 키로서 사용자 ID를 정의하고 같은 것을 사용합니다.

테이블 스키마에서 ON DUPLICATE KEY UPDATE를 사용할 수도 있습니다. 다른 대체 방법은 REPLACE INTO 구문을 사용하는 것입니다.

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

이 기록은 이미 다시 삽입하기 전에 삭제합니다 존재하는 경우, 삽입하려고합니다.

+0

Zend_Db에서'INSERT IGNORE'가 지원됩니까? –

+0

정직하게도 NoFId. –

+0

'IGNORE'는 db 엔진으로 하여금 오류 대신 경고를 내리게하여 질의 실행이 멈추지 않게합니다. 이 접근법의 단점은 * 발생한 모든 오류가 중복 키가 아니라 경고로 무시/전환된다는 것입니다. –

4

은, 제가하는 일은 삽입 문의 시도/캐치하고 예외 코드에 따라 추가 조치를 취할 :

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

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(); 
} 
관련 문제