sql >> データベース >  >> RDS >> Mysql

MySQLに行が存在しない場合に挿入する方法(UPSERT)

    • INSERT IGNOREの使用
    • REPLACEの使用
    • INSERT ... ON DUPLICATE KEY UPDATE

    MySQLは、INSERTが必要な場合に、いくつかの便利なステートメントを提供します。 の行 その行が実際に新しいか、すでに存在するかを判断します。

    以下では、3つの異なる方法を検討し、それぞれの長所と短所を順番に説明して、INSERTIONに新しいデータまたは潜在的に既存のデータを提供するときに独自のステートメントを構成する方法をしっかりと把握できるようにします。 。

    INSERT IGNOREの使用

    INSERT IGNOREの使用 事実上、MySQLは無視します INSERTの実行中に実行エラーが発生しました ステートメント。これは、INSERT IGNOREを意味します UNIQUEに重複する値を含むステートメント インデックスまたはPRIMARY KEY フィールドはしません エラーが発生しますが、代わりにその特定のINSERTを単に無視します 完全にコマンド。明らかな目的は、多数のINSERTを実行することです。 データベースにすでに存在するデータと、システムに入力される新しいデータの両方の組み合わせに関するステートメント。

    たとえば、books テーブルにはすでにいくつかのレコードが含まれている可能性があります:

    mysql> SELECT * FROM books LIMIT 3;
    +----+-------------------------+---------------------+----------------+
    | id | title                   | author              | year_published |
    +----+-------------------------+---------------------+----------------+
    |  1 | In Search of Lost Time  | Marcel Proust       |           1913 |
    |  2 | Ulysses                 | James Joyce         |           1922 |
    |  3 | Don Quixote             | Miguel de Cervantes |           1605 |
    +----+-------------------------+---------------------+----------------+
    3 rows in set (0.00 sec)
    

    INSERTへの新規および既存のデータの大量のバッチがある場合 そのデータの一部には、idに一致する値が含まれています フィールド(UNIQUE PRIMARY_KEY 表内)、基本的なINSERTを使用 予期されるエラーが発生します:

    mysql> INSERT INTO books
        (id, title, author, year_published)
    VALUES
        (1, 'Green Eggs and Ham', 'Dr. Seuss', 1960);
    ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'
    

    一方、INSERT IGNOREを使用する場合 、複製の試行は無視され、結果として生じるエラーは発生しません:

    mysql> INSERT IGNORE INTO books
        (id, title, author, year_published)
    VALUES
        (1, 'Green Eggs and Ham', 'Dr. Seuss', 1960);
    Query OK, 0 rows affected (0.00 sec)
    

    REPLACEの使用

    実際に交換したい場合 INSERTの行 UNIQUEが重複しているため、コマンドでエラーが発生する またはPRIMARY KEY 上記の値の場合、1つのオプションはREPLACEを選択することです。 ステートメント。

    REPLACEを発行する場合 ステートメントでは、発行されたコマンドごとに2つの可能な結果があります。

    • 値が一致する既存のデータ行が見つからないため、標準のINSERT ステートメントが実行されます。
    • 一致するデータ行は 見つかったため、既存の行が標準のDELETEで削除されます ステートメント、次に通常のINSERT 後で実行されます。

    たとえば、REPLACEを使用できます id = 1の既存のレコードを交換します 失われた時間を求めて マルセル・プルーストと緑のたまごとハム ドクター・スース:

    mysql> REPLACE INTO books
        (id, title, author, year_published)
    VALUES
        (1, 'Green Eggs and Ham', 'Dr. Seuss', 1960);
    Query OK, 2 rows affected (0.00 sec)
    

    1つの行のみを変更したにもかかわらず、結果は2つであることを示していることに注意してください。 実際にDELETEDしたため、行が影響を受けました 次に、既存の行をINSERTED 置き換える新しい行。

    REPLACEの使用に関する詳細情報 公式ドキュメントに記載されています。

    INSERT ... ON DUPLICATE KEY UPDATE

    INSERTINGの代替(および一般的に推奨される)方法 重複するUNIQUEを含む可能性のある行に またはPRIMARY KEY 値は、INSERT ... ON DUPLICATE KEY UPDATEを使用することです。 ステートメントと句。

    REPLACEとは異なり – DELETEによる本質的に破壊的なコマンド 必要に応じて実行するコマンド– INSERT ... ON DUPLICATE KEY UPDATEを使用 非破壊的INSERTのみを発行するという点で またはUPDATE ステートメントですが、DELETEは絶対に使用しないでください 。

    たとえば、id = 1を置き換えることにしました。 緑のたまごとハムの記録 元の失われた時間を求めてに戻します 代わりに記録してください。したがって、元のINSERTを使用できます。 ステートメントを作成し、新しいON DUPLICATE KEY UPDATEを追加します 条項:

    mysql> SET @id = 1,
        @title = 'In Search of Lost Time',
        @author = 'Marcel Proust',
        @year_published = 1913;
    INSERT INTO books
        (id, title, author, year_published)
    VALUES
        (@id, @title, @author, @year_published)
    ON DUPLICATE KEY UPDATE
        title = @title,
        author = @author,
        year_published = @year_published;
    

    通常のUPDATEを使用していることに注意してください 構文(ただし、不要なtableは除く 名前とSET キーワード)、non-UNIQUEのみを割り当てる 値。また、ON DUPLICATE KEY UPDATEには不要ですが 正しく機能する方法として、user variablesを利用することも選択しました したがって、INSERTする実際の値を指定する必要はありません。 またはUPDATE 複数回。

    その結果、id = 1 レコードは適切にUPDATED 予想通り:

    mysql> SELECT * FROM books LIMIT 1;
    +----+------------------------+---------------+----------------+
    | id | title                  | author        | year_published |
    +----+------------------------+---------------+----------------+
    |  1 | In Search of Lost Time | Marcel Proust |           1913 |
    +----+------------------------+---------------+----------------+
    1 row in set (0.00 sec)
    

    詳細については、公式ドキュメントをご覧ください。


    1. プリペアドステートメントでテーブル名をパラメータ化できますか?

    2. SQLクエリは複数のテーブルからデータを返します

    3. カンマ区切りの値をOracleの行に変換するにはどうすればよいですか?

    4. PostreSQLに新しい行のみを一括挿入する方法