6

我正在定期解析 json 提要,并且只需要从提要中插入最新用户并忽略现有用户。

我认为我需要的是ON DUPLICATE KEY UPDATEINSERT 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 进行数据库交互 :) 不过我不介意通用的战略解决方案。

4

5 回答 5

5

替代方法允许您将ON DUPLICATE KEY UPDATE更新与插入决策参考数据库:

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

如果用户 ID 为 2 的条目已存在,则将名称字段更新为“Bobby”。

INSERT IGNORE如果您向 UPDATE 提供无效操作,您可以使用它作为替代方法:

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

如果 userid 2 已经存在,这将无济于事,从而避免警告和吞下您在使用INSERT IGNORE.


另一种选择是REPLACE

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

如果用户标识 2 尚不存在,这将执行正常插入。如果确实存在,它将先删除旧条目,然后插入新条目。


请注意,这两个版本都是 MySQL 特定的 SQL 扩展。

于 2009-10-31T11:55:04.137 回答
4

For Zend Framework, what I do is a try/catch of the insert statement and take further action based on the exception code:

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;
    }
}
于 2011-10-24T10:19:10.040 回答
2

您需要将 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');

这将尝试插入,如果记录已经存在,它将在再次插入之前将其删除。

于 2009-10-31T11:29:52.490 回答
1

My solution :

/**
 * 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();
}
于 2013-01-15T13:07:41.947 回答
0

在循环中,您可以先进行更新,如果没有受影响的行,则表示它是一个新条目。跟踪那些“失败的更新”,然后将它们作为新条目插入。

我不熟悉 Zend_Db,但我认为它可以返回更新是否影响了多少行。

于 2009-10-31T11:28:52.430 回答