存在する場合はどのように更新し、存在しない場合は(別名「upsert」または「merge」)をMySQLに挿入しますか?


152

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

回答:


191

を使用し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

10
ええ、SQL Serverの同等の機能はと呼ばれていると思いますMERGE。一般に、この概念はしばしばと呼ばれ"UPSERT"ます。
混乱

3
@blub:あなたは上の一意のキーを作成した場合gebと、topicそれが動作します(ALTER TABLE table ADD UNIQUE geb_by_topic (geb, topic))。
混沌

1
@ブライアン:Oracleの同等のものも呼び出されMERGEますが、その構文がSQL Serverのものと同一であるかどうかはわかりません。
ケン・キーナン

1
@Brooks:0を渡すと、実際には値として0を使用します。だからそれをしないでください。動作をNULL許可するために、何も渡さないでくださいauto_increment。そうでない場合は、想定どおりに機能します。dev.mysql.com/ doc / refman / 5.5 / en / example-auto-incrementを参照してください。 html)。
混乱

3
ありがとうございますVALUES(col)。重複している場合は、を使用して挿入引数から値を取得できます。例:ON DUPLICATE UPDATE b = VALUES(b), c = VALUES(c)
gerrytan 2014年

5

これは古い質問であることは承知していますが、最近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 INTOは異なる公正な警告ですUPDATE。マニュアルにあるようにREPLACE、行が存在する場合は削除し、新しい行を挿入します。(上記の例では「2行の影響を受ける」という面白いことに注意してください。)つまり、既存のレコードのすべての列の値が置き換えられます(一部の列が更新されるだけではありません)。MySQLの動作REPLACE INTOはSqliteの動作とよく似ていINSERT OR REPLACE INTOます。レコードがすでに存在する場合に、いくつかの列のみを更新する(すべての列は更新しない)場合の回避策については、この質問を参照してください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.