Làm cách nào để cập nhật nếu có tồn tại, chèn nếu không (AKA bổ trợ nâng cấp hoặc hoặc hợp nhất) trong MySQL?


152

Có một cách dễ dàng để INSERTmột hàng khi nó không tồn tại, hoặc UPDATEnếu nó tồn tại, sử dụng một truy vấn MySQL?

Câu trả lời:


191

Sử dụng INSERT ... ON DUPLICATE KEY UPDATE. Ví dụ:

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

10
Vâng, tôi tin rằng tương đương với SQL Server được gọi MERGE. Nói chung, khái niệm thường được gọi là "UPSERT".
hỗn loạn

3
@blub: Nếu bạn tạo một khóa duy nhất gebtopicnó sẽ hoạt động ( ALTER TABLE table ADD UNIQUE geb_by_topic (geb, topic)).
hỗn loạn

1
@Brian: Tương đương với Oracle cũng được gọi MERGEnhưng tôi không chắc cú pháp của nó có giống với SQL Server không.
Ken Keenan

1
@Brooks: Nếu bạn vượt qua 0, nó thực sự sẽ sử dụng 0 làm giá trị. Vì vậy, đừng làm điều đó. Đừng vượt qua bất cứ điều gì, hoặc vượt qua nó NULL, để cho phép auto_incrementhành vi hoạt động (nếu không, vâng, hoạt động như bạn đoán, xem dev.mysql.com/doc/refman/5.5/en/example-auto-increment. html ).
hỗn loạn

3
Cảm ơn bạn và bạn có thể sử dụng VALUES(col)để lấy giá trị từ đối số chèn trong trường hợp trùng lặp. Ví dụ:ON DUPLICATE UPDATE b = VALUES(b), c = VALUES(c)
gerrytan

5

Tôi biết đây là một câu hỏi cũ, nhưng Google dẫn tôi đến đây gần đây vì vậy tôi tưởng tượng những người khác cũng đến đây.

@chaos đúng: có INSERT ... ON DUPLICATE KEY UPDATEcú pháp.

Tuy nhiên, câu hỏi ban đầu hỏi về MySQL cụ thể và trong MySQL có REPLACE INTO ...cú pháp. IMHO, lệnh này dễ dàng hơn và đơn giản hơn để sử dụng cho uperts. Từ hướng dẫn:

REPLACE hoạt động chính xác như INSERT, ngoại trừ nếu một hàng cũ trong bảng có cùng giá trị với một hàng mới cho KEY PRIMARY hoặc chỉ mục UNIQUE, hàng cũ sẽ bị xóa trước khi hàng mới được chèn.

Lưu ý đây không phải là SQL chuẩn. Một ví dụ từ hướng dẫn:

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)

Chỉnh sửa: Chỉ là một cảnh báo công bằng mà REPLACE INTOkhông thích UPDATE. Như hướng dẫn nói, REPLACExóa hàng nếu nó tồn tại, sau đó chèn một hàng mới. (Lưu ý funny "2 rows affected" trong ví dụ trên). Nghĩa là, nó sẽ thay thế các giá trị của tất cả các cột của một kỷ lục hiện có (và không chỉ đơn thuần là cập nhật một số cột.) Hành vi của MySQL REPLACE INTOlà giống như là của Sqlite của INSERT OR REPLACE INTO. Xem câu hỏi này cho một số cách giải quyết nếu bạn chỉ muốn cập nhật một vài cột (và không phải tất cả các cột) nếu bản ghi đã tồn tại.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.