Varsa nasıl güncelleyebilirim, yoksa (AKA “upert” veya “merge”) MySQL'e eklerim?


152

Bir MySQL sorgusu kullanarak INSERT, bir satır olmadığında veya UPDATEvarsa bir satır için kolay bir yol var mı?

Yanıtlar:


191

Kullanın INSERT ... ON DUPLICATE KEY UPDATE. Örneğin:

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

10
Evet, SQL Server'ın eşdeğerinin çağrıldığına inanıyorum MERGE. Genel olarak, kavram genellikle olarak adlandırılır "UPSERT".
kaos

3
@blub: Üzerinde benzersiz bir anahtar oluşturursanız gebve topicçalışır ( ALTER TABLE table ADD UNIQUE geb_by_topic (geb, topic)).
kaos

1
@Brian: Oracle'ın eşdeğeri de denir, MERGEancak sözdiziminin SQL Server ile aynı olup olmadığından emin değilim.
Ken Keenan

1
@Brooks: 0 değerini iletirseniz, aslında değer olarak 0 kullanılır. Öyleyse yapma. Davranışın çalışmasına NULLizin vermek için hiçbir şey geçirmeyin veya a geçirmeyin auto_increment(aksi takdirde evet, tahmin ettiğiniz gibi çalışır; bkz. Dev.mysql.com/doc/refman/5.5/en/example-auto-increment. html ).
kaos

3
Teşekkür ederiz ve VALUES(col)yinelenen durumlarda ekleme bağımsız değişkeninden değer almak için kullanabilirsiniz . Örn:ON DUPLICATE UPDATE b = VALUES(b), c = VALUES(c)
gerrytan

5

Bunun eski bir soru olduğunu biliyorum, ancak Google son zamanlarda beni buraya yönlendirdi, bu yüzden başkalarının da buraya geldiğini hayal ediyorum.

@ chaos doğru: INSERT ... ON DUPLICATE KEY UPDATEsözdizimi var.

Ancak, orijinal soru özellikle MySQL hakkında sordu ve MySQL'de REPLACE INTO ...sözdizimi var. IMHO, bu komut upserts için kullanımı daha kolay ve daha basittir. Kılavuzdan:

REPLACE tam olarak INSERT gibi çalışır, ancak tablodaki eski bir satır bir PRIMARY KEY veya UNIQUE dizini için yeni bir satırla aynı değere sahipse, yeni satır eklenmeden önce eski satır silinir.

Bunun standart SQL olmadığını unutmayın. Kılavuzdan bir örnek:

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)

Düzenleme: Sadece adil bir uyarı REPLACE INTOgibi değil UPDATE. Kılavuzda belirtildiği gibi, REPLACEvarsa satırı siler, ardından yeni bir satır ekler. (Yukarıdaki örnekte komik "2 satır etkilenen" dikkat edin.) Yani, varolan bir kaydın tüm sütunlarının değerlerini değiştirir (ve sadece bazı sütunları güncellemekle kalmaz .) MySQL'in davranışı REPLACE INTOSqlite'nin davranışına çok benzer INSERT OR REPLACE INTO. Kayıt zaten varsa yalnızca birkaç sütunu (ve tüm sütunları değil) güncellemek istiyorsanız, bazı geçici çözümler için bu soruya bakın .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.