簡體   English   中英

SQL:只將新行/記錄插入表中?

[英]SQL: Insert only new rows/records into a table?

我正在定期解析json feed並且只需要從feed中插入最新用戶並忽略現有用戶。

我認為我需要的是基於一些搜索的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進行數據庫交互:)我不介意一般的戰略解決方案。

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM