MySQL

2013-11-03, mysql

REPLACEクエリの罠

該当行があったら先に削除してから、新しい行を挿入してくれるREPLACEクエリは使い勝手が良くて度々利用していたのですが、どうやらとんでもない落とし穴があるようです。以下がその再現プロセスです。てっきり主キーをベースに削除行を判断するのかと思っていたのですが、どうやらユニークキーもその対象になってしまうようです。最初に期待していた動作は「主キーの存在を確認し、当該行の削除・挿入トランザクションを実施しようとするが、ユニーク制約にかかりロールバックされる(つまり何も起こらない)」というものですが、実際にはこうなりません。「主キー、ユニークキーをチェックし制約にかかる行を全部取り除いてから、挿入」という動作をしてしまいます。以下の例では実際に行が減ってしまっていることで理解できるかと思います。

mysql> CREATE TABLE t (pk INT NOT NULL,uni INT NOT NULL,v INT NOT NULL,PRIMARY KEY(pk),UNIQUE(uni));
Query OK, 0 rows affected (0.08 sec)

mysql> INSERT INTO t VALUES (1,10,100),(2,20,200),(3,30,300);
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0

mysql> select * from t;
+----+-----+-----+
| pk | uni | v |
+----+-----+-----+
| 1 | 10 | 100 |
| 2 | 20 | 200 |
| 3 | 30 | 300 |
+----+-----+-----+
3 rows in set (0.00 sec)

mysql> REPLACE INTO t VALUES (2,30,999);
Query OK, 3 rows affected (0.00 sec)

mysql> select * from t;
+----+-----+-----+
| pk | uni | v |
+----+-----+-----+
| 1 | 10 | 100 |
| 2 | 30 | 999 |
+----+-----+-----+
2 rows in set (0.00 sec)

参考URL

この記事は役に立ちましたか?