web-dev-qa-db-ja.com

重複レコードのみの選択フィールドを更新しながら、単一のクエリでSELECTおよびUPDATE

私は、たとえば次の内容のContacts_tableという名前のMySQLテーブルを持っています。

ID          NUMBER          NAME            CITY
001         2222222222      John Doe        Los Angeles
002         3333333333      Rich Malfoy     Houston
003         4444444444      Harry Potter    New York
004         5555555555      Billy Bones     Boston
005         6666666666      Joe Sanders     Chicago

* ID:主キー。自動増加

* NUMBER:一意のキー

そして、PHP=を使用して、これらのフィールドの値のコンマ区切りのテキストダンプを読み取り、それらの値を解析して、テーブルに追加します。たとえば、サンプルのテキストダンプには次の内容があります(わかりやすくするために、ここでは表として示しています)。

NUMBER          NAME            CITY
1234567892      Earl Grey       Salem
3333333333      Rich Malfoy     Sacramento
7656453248      Bill Gates      New York
5555555555      James McGill    Boston
6666666666      NULL            Baton Rouge

ご覧のとおり、my TXTにいくつかのエントリ(NUMBERに基づく))があり、テーブルに存在しません。つまり、2番目、4番目、5番目のレコードです。テーブルにはすでに対応するエントリがありますが、他のフィールドの値が異なる可能性があります。コードで実行したいのは、新しいエントリを更新することです(この例ではNUMBER値3333333333、5555555555、および6666666666)。他のエントリと同様に、コードTXTダンプにNULL以外の値が含まれるフィールドのみを更新します。したがって、更新されたテーブルは次のようになります。

ID          NUMBER          NAME            CITY
001         2222222222      John Doe        Los Angeles
002         3333333333      Rich Malfoy     Sacramento
003         4444444444      Harry Potter    New York
004         5555555555      James McGill    Boston
005         6666666666      Joe Sanders     Baton Rouge
006         1234567892      Earl Grey       Salem
007         7656453248      Bill Gates      New York

私が言ったように、既存のエントリがある場合は常に、フィールドの値をチェックする必要があり、対応するTXTダンプにNULL以外の値があるレコードのみが更新されます。

大量のINSERT ON DUPLICATE KEY UPDATEクエリ(基本的には、TXTダンプの各エントリに対して1つ)があります。これは、ダンプが数百のレコードで構成される場合に多くなります。単一のトランザクションでこのタスクを処理する単一のクエリを作成する方法はありますか?

4
TheLearner

uniqueにはnumber制約/インデックスがあるため、_ON DUPLICATE KEY UPDATE_構文を使用できます。これは_INSERT ... VALUES_と組み合わせて、すべての行を挿入/更新できます。 1つのステートメント。新しいnull値が既存の値を更新しないという追加の要件は、COALESCE()関数を使用して満たすことができます。例:

_INSERT INTO Contacts
    (number, name, city)
VALUES
    (1234567892, 'Earl Grey', 'Salem'),
    (3333333333, 'Rich Malfoy', 'Sacramento'),
    (7656453248, 'Bill Gates', 'New York'),
    (5555555555, 'James McGill', 'Boston'),
    (6666666666, NULL, 'Baton Rouge')
ON DUPLICATE KEY UPDATE
    name = COALESCE(VALUES(name), name),
    city = COALESCE(VALUES(city), city) ;
_

SQLfiddle でテストする

4
ypercubeᵀᴹ

別のアプローチ:

  1. LOAD DATA新しい(一時)テーブルに
  2. UPDATE real JOIN new ON ... SET real.x=... WHERE ...-更新が必要な既存の行を更新します
  3. INSERT INTO new SELECT new LEFT JOIN real ON ... WHERE real.id IS NULL-まだ存在しない行を追加します
0
Rick James