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

INSERT IGNORE vs INSERT ... ON DUPLICATE KEY UPDATE

    INSERT...ON DUPLICATE KEY UPDATEを使用することをお勧めします 。

    INSERT IGNOREを使用する場合 の場合、キーが重複する場合、行は実際には挿入されません。ただし、ステートメントはエラーを生成しません。代わりに警告が生成されます。これらのケースには次のものが含まれます:

    • PRIMARY KEYを使用して列に重複キーを挿入します またはUNIQUE 制約。
    • NOT NULLの列にNULLを挿入する 制約。
    • パーティション化されたテーブルに行を挿入しますが、挿入した値はパーティションにマップされません。

    REPLACEを使用する場合 、MySQLは実際にDELETEを実行します 続いてINSERT 内部的には、予期しない副作用があります:

    • 新しい自動インクリメントIDが割り当てられます。
    • 外部キーを持つ依存行が削除されるか(カスケード外部キーを使用する場合)、またはREPLACEが妨げられる可能性があります 。
    • DELETEで起動するトリガー 不必要に実行されます。
    • 副作用はレプリカにも伝播されます。

    修正: 両方のREPLACE およびINSERT...ON DUPLICATE KEY UPDATE MySQLに固有の非標準の独自の発明です。 ANSI SQL 2003は、MERGEを定義します 同じニーズ(およびそれ以上)を解決できるステートメントですが、MySQLはMERGEをサポートしていません ステートメント。

    ユーザーがこの投稿を編集しようとしました(編集はモデレーターによって拒否されました)。編集は、INSERT...ON DUPLICATE KEY UPDATEというクレームを追加しようとしました 新しい自動インクリメントIDが割り当てられます。新しいIDが生成されることは事実です 、ただし、変更された行では使用されません。

    以下のデモを参照してください。PerconaServer5.5.28でテストされています。構成変数innodb_autoinc_lock_mode=1 (デフォルト):

    mysql> create table foo (id serial primary key, u int, unique key (u));
    mysql> insert into foo (u) values (10);
    mysql> select * from foo;
    +----+------+
    | id | u    |
    +----+------+
    |  1 |   10 |
    +----+------+
    
    mysql> show create table foo\G
    CREATE TABLE `foo` (
      `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
      `u` int(11) DEFAULT NULL,
      PRIMARY KEY (`id`),
      UNIQUE KEY `u` (`u`)
    ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1
    
    mysql> insert into foo (u) values (10) on duplicate key update u = 20;
    mysql> select * from foo;
    +----+------+
    | id | u    |
    +----+------+
    |  1 |   20 |
    +----+------+
    
    mysql> show create table foo\G
    CREATE TABLE `foo` (
      `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
      `u` int(11) DEFAULT NULL,
      PRIMARY KEY (`id`),
      UNIQUE KEY `u` (`u`)
    ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1
    

    上記は、IODKUステートメントが重複を検出し、更新を呼び出してuの値を変更することを示しています。 。 AUTO_INCREMENT=3に注意してください IDが生成されたが、行で使用されていないことを示します。

    一方、REPLACE 元の行を削除して新しい行を挿入し、を生成します 新しい自動インクリメントIDの保存:

    mysql> select * from foo;
    +----+------+
    | id | u    |
    +----+------+
    |  1 |   20 |
    +----+------+
    mysql> replace into foo (u) values (20);
    mysql> select * from foo;
    +----+------+
    | id | u    |
    +----+------+
    |  3 |   20 |
    +----+------+
    


    1. UNIX_TIMESTAMP()の例– MySQL

    2. MySQLクエリのIF条件でカウント

    3. 生産性を向上させるためにホームオフィスを整理する

    4. MySQLで欠落している日付を埋める方法は?