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


152

하나의 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".
chaos

3
@blub : 당신이 고유 키를 생성하는 경우 gebtopic그것을 작동합니다 ( ALTER TABLE table ADD UNIQUE geb_by_topic (geb, topic)).
chaos

1
@Brian : Oracle과 동등한 것이 호출 MERGE되지만 구문이 SQL Server와 동일한 지 확실하지 않습니다.
Ken Keenan

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

5

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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.