충돌 업데이트에 PostgreSQL INSERT ON (업소 트) 제외 된 모든 값 사용


142

행을 upserting 할 때 (PostgreSQL> = 9.5) 가능한 INSERT가 가능한 UPDATE와 정확히 동일하게하려면 다음과 같이 작성할 수 있습니다.

INSERT INTO tablename (id, username, password, level, email) 
                VALUES (1, 'John', 'qwerty', 5, 'john@mail.com') 
ON CONFLICT (id) DO UPDATE SET 
  id=EXCLUDED.id, username=EXCLUDED.username,
  password=EXCLUDED.password, level=EXCLUDED.level,email=EXCLUDED.email

더 짧은 방법이 있습니까? 말하자면 : 모든 EXCLUDE 값을 사용하십시오.

SQLite에서는 다음과 같이했습니다.

INSERT OR REPLACE INTO tablename (id, user, password, level, email) 
                        VALUES (1, 'John', 'qwerty', 5, 'john@mail.com')

43
: 아니 진짜 대답하지만 당신은 곧 표기법 약간 사용할 수 있습니다 INSERT INTO tablename (id, username, password, level, email) VALUES (1, 'John', 'qwerty', 5, 'john@mail.com') ON CONFLICT (id) DO UPDATE SET (username, password, level, email) = (EXCLUDED.username, EXCLUDED.password, EXCLUDED.level, EXCLUDED.email).관리 / 붙여 넣기 / 열 목록 거의 동일하지만, 쉽게 사본
새끼

또 다른 옵션은 사용 jsonb 컬럼에이고 그런 식으로 당신은 컬럼에 대해 걱정할 필요가 없습니다
J 것이다

답변:


162

Postgres는에 해당하는 것을 구현하지 않았습니다 INSERT OR REPLACE. 로부터 ON CONFLICT문서 (강조 광산) :

DO NOTHING이거나 충돌시 수행 할 UPDATE 조치 의 정확한 세부 사항 을 지정하는 DO UPDATE 절일 수 있습니다 .

교체에 대한 단축은 아니지만 ON CONFLICT DO UPDATE기존 데이터를 기반으로 새 값을 설정할 수 있으므로보다 일반적으로 적용됩니다. 예를 들면 다음과 같습니다.

INSERT INTO users (id, level)
VALUES (1, 0)
ON CONFLICT (id) DO UPDATE
SET level = users.level + 1;

3
주의 할 점으로, "업데이트시"는 SQL 표준의 "병합"과 의미 상 동일하지 않지만 일반적으로 동일한 위치에서 사용할 수 있습니다. "충돌시 업데이트"가 시작될 것으로 예상했지만 삽입의 정확한 문제로 인해 업데이트 (손상된 레코드를 복구했을 수 있음)가 발생하지 않았습니다.
pojo-guy

2
"삽입의 정확한 문제로 인해 업데이트가 발생하지 않았습니다"로 확장 할 수 있습니까?
MrR

@ pojo-guy-MrR의 질문을 보지 못했다고 생각합니다- "삽입의 정확한 문제로 인해 업데이트가 발생하지 않았습니다."
랜달

postgresql에서 업데이트시 insert ...를 사용하려고하면 특정 상황에서는 병합과 결과가 다릅니다. 내가 만난 사건은 다소 모호하고 구체적 이었지만 반복 가능했습니다. 몇 달이 지났으므로 더 이상 알 수 없습니다.
pojo-guy

아마도 충돌이 아닌 필드 유형 오류와 같은 다른 오류입니까?
MrR
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.