web-dev-qa-db-ja.com

存在する場合はどのように更新し、存在しない場合(別名「アップサート」または「マージ」)をMySQLに挿入しますか?

1つのMySQLクエリを使用して、行が存在しないときにINSERT行に、または存在する場合にUPDATEに簡単な方法はありますか?

150
blub

はい、 - INSERT ... ON DUPLICATE KEY UPDATE 。例えば:

INSERT INTO `usage`
(`thing_id`, `times_used`, `first_time_used`)
VALUES
(4815162342, 1, NOW())
ON DUPLICATE KEY UPDATE
`times_used` = `times_used` + 1
189
chaos

これは古い質問ですが、最近Googleがここに私を導いてくれたので、他の人もここに来ると思います。

@chaosは正しい: INSERT ... ON DUPLICATE KEY UPDATE 構文。

ただし、元々の質問はMySQLについて具体的に尋ねたもので、MySQLには REPLACE INTO ... 構文。私見、このコマンドはアップサートに使用する方が簡単で簡単です。マニュアルから:

REPLACEはINSERTとまったく同じように機能しますが、テーブル内の古い行がPRIMARY KEYまたはUNIQUEインデックスの新しい行と同じ値を持つ場合、古い行は新しい行が挿入される前に削除されます。

これは標準SQLではないことに注意してください。マニュアルの例:

CREATE TABLE test (
  id INT UNSIGNED NOT NULL AUTO_INCREMENT,
  data VARCHAR(64) DEFAULT NULL,
  ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (id)
);

mysql> REPLACE INTO test VALUES (1, 'Old', '2014-08-20 18:47:00');
Query OK, 1 row affected (0.04 sec)

mysql> REPLACE INTO test VALUES (1, 'New', '2014-08-20 18:47:42');
Query OK, 2 rows affected (0.04 sec)

mysql> SELECT * FROM test;
+----+------+---------------------+
| id | data | ts                  |
+----+------+---------------------+
|  1 | New  | 2014-08-20 18:47:42 |
+----+------+---------------------+
1 row in set (0.00 sec)

編集:REPLACE INTOUPDATEとは異なります。マニュアルにあるように、REPLACEは行が存在する場合は削除し、新しい行を挿入します。 (上記の例の面白い「2行の影響」に注意してください。)つまり、既存のレコードのall列の値を置き換えます(更新someカラム。)MySQLのREPLACE INTOは、SqliteのINSERT OR REPLACE INTO。レコードが既に存在する場合にいくつかの列(すべての列ではなく)のみを更新する場合の回避策については、 この質問 を参照してください。

4
Armadillo Jim