6

私は定期的にjsonフィードを解析しており、フィードから最新のユーザーのみを挿入し、既存のユーザーを無視する必要があります。

私が必要としているのは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を使用しています:)しかし、一般的な戦略的ソリューションは気にしません。

4

5 に答える 5

5

別のON DUPLICATE KEY UPDATE方法では、更新と挿入の決定をデータベースに参照できます。

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

ユーザーID2のエントリがすでに存在する場合は、名前フィールドを「Bobby」に更新します。

INSERT IGNOREUPDATEに無効な操作を指定した場合の代わりに、これを使用できます。

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

ユーザーID2がすでに存在する場合、これは何もしません。したがって、を使用するときに発生する他のエラーの警告や飲み込みを回避しますINSERT IGNORE


別の選択肢は次のようになりますREPLACE

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

ユーザーID2がまだ存在しない場合、これは通常の挿入を行います。存在する場合は、最初に古いエントリを削除してから、新しいエントリを挿入します。


どちらのバージョンもSQLに対するMySQL固有の拡張機能であることに注意してください。

于 2009-10-31T11:55:04.137 に答える
4

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

ユーザーIDをPRIMARYまたはUNIQUEキーとして定義し、次のようなものを使用する必要があります。

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

ユーザーID2がすでに存在する場合、それは無視され、次の挿入に進みます。

テーブルスキーマでONDUPLICATEKEYUPDATEを使用することもできます。もう1つの方法は、REPLACEINTO構文を使用することです。

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

これはINSERTを試みます。レコードがすでに存在する場合は、再度INSERTする前にDELETEします。

于 2009-10-31T11:29:52.490 に答える
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();
}
于 2013-01-15T13:07:41.947 に答える
0

ループでは、最初に更新を実行できます。影響を受ける行がない場合は、それが新しいエントリであることを意味します。それらの「失敗した更新」を追跡し、新しいエントリとしてそれらを挿入します。

私はZend_Dbに精通していませんが、更新が行数に影響したかどうかを返すことができると思います。

于 2009-10-31T11:28:52.430 に答える