[sql] 존재하는 경우 어떻게 업데이트하고 MySQL에없는 경우 삽입 (AKA “upsert”또는 “merge”)합니까?

하나의 MySQL 쿼리를 사용하여 INSERT행이 존재하지 않거나 존재하는 경우 행에 대한 쉬운 방법이 UPDATE있습니까?



답변

사용하십시오 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


답변

나는 이것이 오래된 질문이라는 것을 알고 있지만 Google이 최근에 나를 이끌 기 때문에 다른 사람들도 여기에 온 것 같습니다.

@chaos가 정확 INSERT ... ON DUPLICATE KEY UPDATE합니다. 구문이 있습니다.

그러나 원래의 질문은 MySQL에 대해 구체적으로 물었고 MySQL에는 REPLACE INTO ...구문이 있습니다. IMHO,이 명령은 upsert에 사용하기 쉽고 더 간단합니다. 매뉴얼에서 :

REPLACE는 테이블의 이전 행이 PRIMARY KEY 또는 UNIQUE 인덱스의 새 행과 동일한 값을 갖는 경우 새 행이 삽입되기 전에 이전 행이 삭제된다는 점을 제외하고는 INSERT와 똑같이 작동합니다.

이것은 표준 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. 레코드가 이미 존재하는 경우 일부 열만 업데이트하고 일부 열만 업데이트하려는 경우 일부 해결 방법 은 이 질문 을 참조하십시오 .


답변