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.