MySQL 테이블에 삽입하거나 존재하는 경우 업데이트


875

데이터베이스 테이블에 행을 추가하고 싶지만 동일한 고유 키가있는 행이 있으면 행을 업데이트하고 싶습니다.

예를 들면 다음과 같습니다.

insert into table (id, name, age) values(1, "A", 19)

고유 키는 id이고 내 데이터베이스 에는 행 이 있다고 가정 해 봅시다 id = 1. 이 경우 해당 값을 해당 행으로 업데이트하고 싶습니다. 일반적으로 오류가 발생합니다.
내가 사용 insert IGNORE하면 오류를 무시하지만 여전히 업데이트되지는 않습니다.


5
SQL은 구문에서 값을 강제로 복제하지 않고 기본 키를 유지하는이 사용 사례에 대한 공식 구문이 필요합니다.
피트 알빈

영향을받는 ID를 얻으려면 MySQL ON DUPLICATE KEY-마지막 삽입 ID를
Kris Roofe

주의 사항 : 버전 5.7 부터이 방법은 INSERT / UPDATE 작업의 일부로 WHERE 절을 직접 지원하지 않습니다. 또한 UPDATE는 실제로 감사 목적으로 중요한 경우 두 개의 개별 작업 (DELETE 및 INSERT)으로 계산됩니다. (Learnbit)
dreftymac

답변:


1599

사용하다 INSERT ... ON DUPLICATE KEY UPDATE

질문:

INSERT INTO table (id, name, age) VALUES(1, "A", 19) ON DUPLICATE KEY UPDATE    
name="A", age=19

86
+1 내가 찾은 것으로부터,이 방법은 REPLACE INTO보다 자동 증가 키 및 기타 고유 키 충돌에 덜 문제가되지 않으며보다 효율적입니다.
Andrew Ensley

46
나는 당신들 모두가 이것을 암시한다고 알고 있지만, 나는 다른 사람들을 위해 명시 적이기를 원합니다. 삽입 한 ID가 PRIMARY KEY 또는 UNIQUE가 아닌 경우 작동하지 않습니다. 내 ID가 고유하지 않아 처음에는 효과가 없었습니다.
Keven

7
하나의 행을 성공적으로 업데이트 할 때 affected row count결과가 왜 궁금 2합니까? 다른 사람이이 결과를 얻었습니까? (데이터가 올바르게 업데이트 됨 : 한 행만 업데이트됨을 의미)
Dimitry K

14
이것은 조금 늦었지만 어쨌든 :에 명시되어 수동 으로 업데이트하는 것이 ON DUPLICATE KEY UPDATE아무것도 실제로 (일반과 동일 업데이트되지 않은 경우 증가 (2)에 의해 영향을받는 행은 0을보고 UPDATE).
Vatev

61
또한 삽입하려고하는 값 (예 : INSERT INTO 테이블 (ID, 이름, 나이))을 참조하기 위해 VALUES (이름)를 사용할 수 있습니다. DUPLICATE KEY UPDATE name = VALUES (name) , age = VALUES (나이)
Curious Sam

246

교체 확인

http://dev.mysql.com/doc/refman/5.0/en/replace.html

REPLACE into table (id, name, age) values(1, "A", 19)

11
@Piontek 이것은 짧고 이해하기 쉽고 왜 "삽입시 삽입"이 더 좋은지 아무도 설명하지 않았기 때문에.
Mr_Chimp 2016 년

77
레코드의 ID를 변경하므로 외부 참조를 파괴 할 수 있습니다.
boh

102
REPLACE INTO의 다른 문제점 은 모든 필드에 값을 지정 해야 한다는 것입니다 . 그렇지 않으면 필드가 손실되거나 기본값으로 대체됩니다. REPLACE INTO 는 행이 존재하는 경우 본질적으로 삭제 하고 새 행을 삽입합니다. 이 예에서 'REPLACE INTO 테이블 (id, age) 값 (1, 19)을 수행 한 경우 이름 필드는 널이됩니다.
Dale

33
이것은 실제로 전체 행을 삭제하고 새로운 INSERT를 수행합니다.
mjb

8
@mjb 따라서 DELETE 권한이 필요하며, 필요하지 않은 경우에는 사용하지 않는 것이 가장 좋습니다. 내 환경의 데이터베이스 사용자에게는 INSERT 및 UPDATE 권한 만 있으므로 REPLACE가 작동하지 않습니다.
ndm13

54

일괄 삽입을 사용하는 경우 다음 구문을 사용하십시오.

INSERT INTO TABLE (id, name, age) VALUES (1, "A", 19), (2, "B", 17), (3, "C", 22)
ON DUPLICATE KEY UPDATE
    name = VALUES (name),
    ...

새로운 가치
Hunger

VALUES(name)작동하지 않는 경우 시도 할 수 있습니다name = 'name_value',...;
Son Pham

26

이것을 시도하십시오 :

INSERT INTO table (id, name, age) VALUES (1, 'A', 19) ON DUPLICATE KEY UPDATE id = id + 1;

도움이 되었기를 바랍니다.


6
실제로 나는 새로운 ID로 다른 행에 새로운 값을 추가 할 필요가 없으며 대신 id = 1의 기존 값을이 값으로 바꾸고 싶습니다. (I이 증가에게 자료를 이해하고 데이터를 추가로)
Keshan

49
나는 그가 중복으로 ID를 하나씩 늘리고 싶지 않다고 생각합니다.
Donnie

7
"transgress"는 당신이 찾고있는 단어가 아닙니다 :) 불행히도, 이제 "transgress"를 보았습니다. 더 이상 실제 단어를 시각화 할 수 없습니다 ..
mwfearnley

1
"트래버스"또는 "커버"를 찾고 있었습니까?
Chris Dev

4
@mwfearnley 시각화하려는 단어는 "초월"입니다. 단지 1 년 반이 걸렸습니다 :-)
Michael Krebs

20

이 시도:

INSERT INTO table (id,name,age) VALUES('1','Mohammad','21') ON DUPLICATE KEY UPDATE name='Mohammad',age='21'

참고 :
여기서 id가 기본 키인 경우 삽입을 id='1'시도 할 때마다 처음 삽입 한 후 id='1'이름과 연령이 업데이트되고 이전 이름 ​​연령이 변경됩니다.


id 사용하지 않고 일하고 싶습니다 . 기본 키없이 시도 했습니까?
ersks

@ersks는 질문을 참조하십시오. 사용자가 고유 키가 있는지 묻습니다
Rasel

나는 그것을 얻었지만이 유일한 가치를 알고있는 내 문제를 해결하려고합니다. 따라서 그러한 상황에서 올바른 해결책을 기대하면서 위의 의견을 썼습니다.
ersks

15
INSERT IGNORE INTO table (id, name, age) VALUES (1, "A", 19);

INSERT INTO TABLE (id, name, age) VALUES(1, "A", 19) ON DUPLICATE KEY UPDATE NAME = "A", AGE = 19;

REPLACE INTO table (id, name, age) VALUES(1, "A", 19);

이 모든 해결책은 귀하의 질문과 관련하여 작동합니다.

이 진술에 대해 자세히 알고 싶다면 이 링크를 방문하십시오.


REPLACE링크 된 문서에는 문서화되어 있지 않습니다.
Ray Baxter

오타로 가득 찬 SQL 쿼리는 예제가 작동하지 않습니다. INTO TABLE (INTO TABLE 아님) 및 ON DUPLICATE KEY UPDATE (DUPLICATE UPDATE SET 아님)입니다. 누가 이것을지지하는지 잘 모르겠습니다
Robert Sinclair

1
오타 오류로 죄송합니다. 수정 해 주셔서 감사합니다
Dilraj Singh

11

SQLite를 사용하는 경우 :

REPLACE into table (id, name, age) values(1, "A", 19)

그 제공 id의 기본 키입니다. 그렇지 않으면 다른 행을 삽입합니다. INSERT (SQLite)를 참조하십시오 .


replace into정확히 "존재할 때 삽입 또는 업데이트" 란 무엇입니까? @Owl
DawnSong

+1 (1 of 3) 상황에 따라 작동하는 것으로 나타났습니다. 기존 행을 고유 키로 바꾸거나없는 경우 행을 추가해야했습니다. 가장 간단한 솔루션입니다.
therobyouknow

(2/3) 내 질문 :CREATE TRIGGER worklog_update AFTER INSERT ON worklog FOR EACH ROW REPLACE INTO support_time_monthly_hours ( ProjectID, monthTotalTime, Year, Month ) SELECT jiraissue.PROJECT, SUM(worklog.timeworked), YEAR(CURRENT_DATE()), MONTH(CURRENT_DATE()) FROM worklog, jiraissue WHERE worklog.issueid = jiraissue.ID AND jiraissue.PROJECT = (SELECT PROJECT FROM jiraissue WHERE NEW.issueid = jiraissue.ID ) AND worklog.startdate BETWEEN DATE_FORMAT(NOW() ,'%Y-%m-01 00:00:00') AND NOW();
therobyouknow

(
3/3

2
mysql 에서이 문제는 replace가 다른 값을 제공하지 않으면 제거 할 것입니다. 그러나 @ fabiano-souza 솔루션이 더 적합합니다
Quamber Ali

11

여기 에이 솔루션을 찾고 있었지만 동일한 구조화 된 다른 테이블 (내 경우 웹 사이트 테스트 DB를 라이브 DB로 업데이트)에서 업데이트하려고했기 때문에 :

INSERT  live-db.table1
SELECT  *
FROM    test-db.table1 t
ON DUPLICATE KEY UPDATE
        ColToUpdate1 = t.ColToUpdate1,
        ColToUpdate2 = t.ColToUpdate2,
        ...

다른 곳에서 언급했듯이 업데이트하려는 열만 포함해야합니다 ON DUPLICATE KEY UPDATE.

INSERT또는에 열을 나열 할 필요는 SELECT없지만 아마도 더 나은 방법이라고 생각합니다.


4

non-primary대한 기준 / 조건 으로 필드 를 만들려는 경우 해당 테이블에서 키를 ON DUPLICATE생성하여 UNIQUE INDEX를 트리거 할 수 DUPLICATE있습니다.

ALTER TABLE `table` ADD UNIQUE `unique_index`(`name`);

두 필드를 결합하여 테이블에서 고유하게 만들려면 마지막 매개 변수에 더 많은 값을 추가하여이를 수행 할 수 있습니다.

ALTER TABLE `table` ADD UNIQUE `unique_index`(`name`, `age`);

참고, 그냥 있는지 먼저 같은이 데이터를 삭제할 수 있도록 name하고 age다른 행에서 값입니다.

DELETE table FROM table AS a, table AS b WHERE a.id < b.id 
AND a.name <=> b.name AND a.age <=> b.age;

그런 다음 ON DUPLICATE이벤트를 트리거해야합니다 .

INSERT INTO table (id, name, age) VALUES(1, "A", 19) ON DUPLICATE KEY UPDATE    
name = VALUES(name), age = VALUES(age)

2

내 경우에는 내가 경우 쿼리 아래에 있지만 첫 번째 쿼리에서 생성 된 id1이 이미 존재하고 당신이없이 첫 번째 쿼리를 것을 만들 경우 후 나이는 이미이 age값보다 age아무도 없을 것입니다

REPLACE into table SET `id` = 1, `name` = 'A', `age` = 19

위의 문제를 피하기 위해 아래와 같은 쿼리를 작성하십시오.

INSERT INTO table SET `id` = '1', `name` = 'A', `age` = 19 ON DUPLICATE KEY UPDATE `id` = "1", `name` = "A",`age` = 19

그것이 당신을 도울 것입니다 ...


2
왜 우리가 값을 두 번 할당 해야하는지 알고 있습니까? MySQL에서 모든 할당 문을 복제하지 않고 ON DUPLICATE KEY UPDATE시 쿼리를 종료 할 수없는 이유는 무엇입니까? 일부 데이터베이스 테이블에는 많은 열이 있으며 이는 중복 / 무미 한 것으로 보입니다. 대체 과제를 선택할 수있는 옵션이있는 이유를 이해하지만 생략 할 수있는 옵션이없는 이유는 무엇입니까? 누군가 알고 있다면 궁금합니다.
Blue Water

2

이전 필드를 유지하려는 경우 (예 : 이름). 쿼리는 다음과 같습니다.

INSERT INTO table (id, name, age) VALUES(1, "A", 19) ON DUPLICATE KEY UPDATE    
name=name, age=19;
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.