SQLite INSERT-ON DUPLICATE KEY UPDATE (UPSERT)


98

MySQL에는 다음과 같은 것이 있습니다.

INSERT INTO visits (ip, hits)
VALUES ('127.0.0.1', 1)
ON DUPLICATE KEY UPDATE hits = hits + 1;

이 기능이 SQLite에 존재하지 않는다는 것을 알고있는 한 제가 알고 싶은 것은 두 개의 쿼리를 실행하지 않고도 동일한 효과를 얻을 수있는 방법이 있는지 여부입니다. 또한 이것이 가능하지 않은 경우 선호하는 것은 무엇입니까?

  1. SELECT + (INSERT 또는 UPDATE) 또는
  2. UPDATE ( 업데이트가 실패하면 + INSERT )

답변:


31

3.24.0 이후 SQLite는 upsert도 지원 하므로 이제 다음과 같이 간단히 작성할 수 있습니다.

INSERT INTO visits (ip, hits)
VALUES ('127.0.0.1', 1)
ON CONFLICT(ip) DO UPDATE SET hits = hits + 1;

3
upsert하나의 트랜잭션, 즉 Python executemany()함수로 이와 같은 여러 작업을 수행 할 수 있는지 궁금 합니다.
라디오 제어

117
INSERT OR IGNORE INTO visits VALUES ($ip, 0);
UPDATE visits SET hits = hits + 1 WHERE ip LIKE $ip;

이를 위해서는 "ip"열에 UNIQUE (또는 PRIMARY KEY) 제약 조건이 있어야합니다.


편집 : 또 다른 훌륭한 솔루션 : https://stackoverflow.com/a/4330694/89771 .


2
기록을 위해서만 REPLACE옵션이 아닙니다.
Alix Axel 2012

1
은 "다른 훌륭한 솔루션"링크에 관해서는, 나는 또한 같은 질문에 다른 대답을 고려할 것입니다 : stackoverflow.com/a/418988/3650835
KayakinKoder

19

나는 선호한다 UPDATE (+ INSERT if UPDATE fails). 더 적은 코드 = 더 적은 버그.


1
감사! @Sam ( stackoverflow.com/questions/418898/… )이 동의하는 것 같습니다. 나는 또한이 접근 방식을 선호합니다.
Alix Axel

@Smith 나는 일반 UPDATE 및 INSERT 문을 사용하고 반환 값을 확인하는 것을 의미했습니다.
codeholic

이것은 원 자성이 없으며 다른 프로세스가 중간에 삽입되면 INSERT가 실패 할 수 있습니다.
Robin Lavallée

7

현재 답변은 sqlite OR mysql에서만 작동합니다 (OR 사용 여부에 따라 다름). 따라서 dbms 간 호환성을 원하면 다음을 수행합니다.

REPLACE INTO `visits` (ip, value) VALUES ($ip, 0);

3
받아 들여지는 대답은 SQLite에서 작동합니다 (내 목표였습니다). REPLACESQLite에서도 작동하지만 MySQL에서는 항상 카운터를 0으로 재설정합니다. 쿼리는 이식 가능하지만 최종 결과는 많이 다릅니다.
Alix Axel 2012

당신 말이 맞아요, OP가 휴대 가능한 것을 찾고 있다고 생각했습니다. REPLACE INTO가 모든 경우, 특히 PK 보존이 필요한 경우에는 작동하지 않지만 많은 경우에 작동한다는 것을 알고 있습니다.
Jacob Thomason

데이터를 버리는 대신 깔끔하게 실패하는 것은 버그가 아니라 기능입니다.
Tobu 2013

-4

단일 값 (방문 수)을 저장하는 단일 키 (IP 주소)이므로이를 위해 memcached를 사용해야합니다. 원자 증가 함수를 사용하여 "경쟁"조건이 없는지 확인할 수 있습니다.

MySQL보다 빠르며 부하를 줄여 MySQL이 다른 일에 집중할 수 있습니다.


데이터가 그렇게 중요하지 않다면 그렇습니다. 그러나 많은 IP가 서비스에 도달하는 바쁜 사이트에서 이것이 사용되는 경우 memcached 인스턴스가 가득 차서 일부 콘텐츠가 삭제 될 수 있습니다. memcached 콘텐츠를 백업하는 것도 흥미로울 것입니다 (필요한 경우).
Elliot Foster

@ElliotFoster Memcached는 여러분이 던지는 RAM만큼 많은 데이터를 처리 할 수 ​​있습니다 (지속성을 원한다면 redis 또는 membase도 사용하십시오). 하루에 100 만 명 이상의 방문자가 발생하는 경우 Memcache 인스턴스에 30MB 이상의 램 (내 생각에 기본값)을 제공 할 여유가있을 것입니다. 그러나 제공하는 메모리 양에 대해 SQLite 및 MySQL보다 훨씬 더 많은 부하를 확실히 처리 할 수 ​​있습니다. 비교할 수는 없습니다.
Xeoncross

내 의견을 memcache에 대한 투표로 착각하지 마십시오. 환상적인 도구라고 생각합니다. redis와 마찬가지로 (내가 사용하지 않았기 때문에 membase에 대해 말할 수 없습니다.) 그러나 memcache / redis는 가장 안정적인 저장소가 아닙니다. 예, redis에는 지속성이 있지만 데이터는 (마지막으로 본) 간격으로 디스크에 유지되며 Memcache는 전혀 유지되지 않습니다. 내가 말했듯이 데이터가 중요하지 않거나 쉽게 복제 할 수 있다면 memcache와 회사는 훌륭합니다. 원래 게시물은 또한 MySQL과 매우 다른 sqlite에 대해 묻고 있었으며 다른 방식으로 제한 될 가능성이 높습니다.
Elliot Foster

원하는만큼 빠르게 데이터를 유지하도록 Redis를 구성 할 수 있습니다 (X 초 또는 Y 번 변경).
Buffalo
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.