테이블의 행을 업데이트하거나 존재하지 않는 경우 삽입하려면 어떻게 해야 합니까?
다음 카운터 테이블이 있습니다.
CREATE TABLE cache (
key text PRIMARY KEY,
generation int
);
카운터 중 하나를 늘리거나 해당 행이 아직 존재하지 않으면 0으로 설정합니다.표준 SQL에서 동시성 문제 없이 이를 수행할 수 있는 방법이 있습니까?작업은 트랜잭션의 일부이거나 분리될 수 있습니다.
SQLite, Postgre에서 SQL을 변경하지 않고 실행해야 합니다.SQL 및 MySQL(가능한 경우).
검색 결과 동시성 문제로 인해 문제가 발생하거나 데이터베이스에 고유한 여러 가지 아이디어가 발견되었습니다.
노력하다
INSERT
새로운 행과UPDATE
에러가 있었을 경우.불행히도 에러는INSERT
현재 트랜잭션을 중단합니다.UPDATE
행 및 행이 변경되지 않은 경우INSERT
새 줄MySQL에는
ON DUPLICATE KEY UPDATE
절을 클릭합니다.
편집: 좋은 답변 감사합니다.폴의 말이 맞는 것 같습니다.휴대폰으로 할 수 있는 방법은 단 하나뿐이 아닙니다.아주 기본적인 수술인 것 같은데 놀랍네요.
MySQL(이후 SQLite)은 REPLACE INTO 구문도 지원합니다.
REPLACE INTO my_table (pk_id, col1) VALUES (5, '123');
그러면 기본 키가 자동으로 식별되고 업데이트할 일치하는 행이 검색되며, 찾을 수 없는 경우 새 행을 삽입합니다.
문서: https://dev.mysql.com/doc/refman/8.0/en/replace.html
SQLite는 행이 이미 있는 경우 이를 대체할 수 있습니다.
INSERT OR REPLACE INTO [...blah...]
이 값을 다음과 같이 줄일 수 있습니다.
REPLACE INTO [...blah...]
이 바로 가기는 MySQL과 호환되도록 추가되었습니다.REPLACE INTO
표현.
저는 다음과 같은 것을 하고 싶습니다.
INSERT INTO cache VALUES (key, generation)
ON DUPLICATE KEY UPDATE (key = key, generation = generation + 1);
코드 또는 SQL에서 생성 값을 0으로 설정하지만,는 ON DUP...를 사용하여 값을 증가시킵니다.어쨌든 그런 구문인 것 같아요.
ON DUPLICATE KEY UPDATE 절이 가장 좋은 해결책입니다.이는 REPLACE가 DELETE를 실행한 후 INSERT를 실행하므로 레코드가 삭제되기 때문에 REPLACE 쿼리 중에 페이지가 표시되었을 경우 쿼리가 다시 돌아올 가능성이 매우 낮기 때문입니다.
INSERT가 더 좋아요...중복 업데이트 시... 이러한 이유로 인해
jmoz의 솔루션이 최고입니다.단, 괄호보다는 SET 구문을 선호합니다.
INSERT INTO cache
SET key = 'key', generation = 'generation'
ON DUPLICATE KEY
UPDATE key = 'key', generation = (generation + 1)
;
플랫폼 중립적인 솔루션을 찾을 수 있을지 모르겠습니다.
이것은 일반적으로 "UPSERT"라고 불립니다.
관련 설명을 참조해 주세요.
포스트그레SQL에는 merge 명령어가 없습니다.실제로 이 명령어를 쓰는 것은 간단하지 않습니다.실제로 작업을 "재미있게" 만드는 이상한 엣지 케이스가 있습니다.
가장 좋은 방법(와 같이: 가장 가능한 조건에서 작업)은 수동(merge_db)에 나와 있는 것과 같은 기능을 사용하는 것입니다.
기능을 사용하고 싶지 않은 경우는, 다음의 조작을 피할 수 있습니다.
updated = db.execute(UPDATE ... RETURNING 1)
if (!updated)
db.execute(INSERT...)
이것은 폴트 프루프가 아니기 때문에, 최종적으로 실패하는 것을 잊지 말아 주세요.
표준 SQL은 이 작업에 대한 MERGE 문을 제공합니다.일부 DBMS는 MERGE 문을 지원하지 않습니다.
(예를 들어 트랜잭션을 통해) 원자적으로 업데이트하거나 삽입하는 일반적인 방법이 없는 경우 다른 잠금 방식으로 폴백할 수 있습니다.0바이트 파일, 시스템 뮤텍스, 명명된 파이프 등...
인서트 트리거를 사용할 수 있습니까?실패할 경우 업데이트를 수행합니다.
SQL을 쓰는 라이브러리를 사용해도 괜찮다면 Upsert를 사용할 수 있습니다(현재는 Ruby와 Python만 해당).
Pet.upsert({:name => 'Jerry'}, :breed => 'beagle')
Pet.upsert({:name => 'Jerry'}, :color => 'brown')
MySQL, Postgres 및 SQLite3에서 사용할 수 있습니다.
MySQL Postgres my my my 、 UDF ( UDF ) 。 it it를 한다.INSERT OR REPLACE
SQLite3를 사용합니다.
언급URL : https://stackoverflow.com/questions/690632/how-do-i-update-a-row-in-a-table-or-insert-it-if-it-doesnt-exist
'programing' 카테고리의 다른 글
php 스크립트에서 ssh를 통해 가상 시스템의 mariadb에 연결하지 못함 (0) | 2022.09.27 |
---|---|
Java 8에서 여러 필드 이름으로 그룹화 (0) | 2022.09.27 |
VARB란INALY(MAX)는? (0) | 2022.09.27 |
System.gc()는 언제 어떤 처리를 합니까? (0) | 2022.09.27 |
CentOS에 Java SDK를 설치하는 방법 (0) | 2022.09.27 |