복붙노트

[SQL] 존재하지 않는 경우 어떻게하면 테이블의 행을 갱신 또는 삽입합니까?

SQL

존재하지 않는 경우 어떻게하면 테이블의 행을 갱신 또는 삽입합니까?

나는 카운터 다음 표를 가지고 :

CREATE TABLE cache (
    key text PRIMARY KEY,
    generation int
);

나는 카운터를 증가 싶은, 또는 해당 행이 아직 존재하지 않는 경우 0으로 설정합니다. 표준 SQL에서 동시성 문제없이 할 수있는 방법이 있나요? 동작은 때때로 분리, 때로는 트랜잭션의 일부입니다.

가능하면 SQL은, SQLite는, PostgreSQL의와 MySQL에 수정되지 않은 실행해야합니다.

수색 중 하나 동시성 문제로 고통, 또는 데이터베이스에 고유 한 몇 가지 아이디어를 얻었다 :

편집 : 모든 위대한 답변을 주셔서 감사합니다. 바울은 바로이며,이 일을 하나의 휴대용 방법이 아니다 것 같습니다. 그것은 아주 기본적인 작업 같은 소리로 즉 아주, 나에게 놀라운.

해결법

  1. ==============================

    1.MySQL을 (그리고 이후 SQLite는) 또한 REPLACE INTO 구문을 지원합니다

    MySQL을 (그리고 이후 SQLite는) 또한 REPLACE INTO 구문을 지원합니다

    REPLACE INTO my_table (pk_id, col1) VALUES (5, '123');
    

    이것은 자동으로 기본 키를 식별하고 아무 것도 발견되지 않으면 새를 삽입, 갱신에 일치하는 행을 찾습니다.

  2. ==============================

    2.이미있는 경우 행을 교체 SQLite는 지원 :

    이미있는 경우 행을 교체 SQLite는 지원 :

    INSERT OR REPLACE INTO [...blah...]
    

    당신이 단축 될 수 있습니다

    REPLACE INTO [...blah...]
    

    이 바로 가기는 MySQL을 표현 INTO 교체와 호환 될 수 있도록 하였다.

  3. ==============================

    3.나는 다음과 같은 일을 할 것입니다 :

    나는 다음과 같은 일을 할 것입니다 :

    INSERT INTO cache VALUES (key, generation)
    ON DUPLICATE KEY UPDATE (key = key, generation = generation + 1);
    

    코드 또는 SQL에서 0으로 생성 값을 설정하지만, 값을 증가 할 ... ON DUP를 사용하여. 나는 어쨌든 구문 생각합니다.

  4. ==============================

    4.를 ON DUPLICATE KEY UPDATE 절은 최고의 솔루션으로 인해입니다 : REPLACE는 INSERT 다음에 DELETE 때문에 레코드가 쿼리 페이지가 동안 볼 경우 쿼리를 교체하는 것이 생략 한 돌아올 수 있다는 아무리 약간의 가능성을 만들어 제거하는 아무리 약간의 기간 동안 수행합니다.

    를 ON DUPLICATE KEY UPDATE 절은 최고의 솔루션으로 인해입니다 : REPLACE는 INSERT 다음에 DELETE 때문에 레코드가 쿼리 페이지가 동안 볼 경우 쿼리를 교체하는 것이 생략 한 돌아올 수 있다는 아무리 약간의 가능성을 만들어 제거하는 아무리 약간의 기간 동안 수행합니다.

    나는 그 이유가 ... INSERT ... ON DUPLICATE UPDATE를 선호합니다.

    jmoz의 솔루션은 최고입니다 : 나는 괄호로 SET 구문을 선호하지만

    INSERT INTO cache 
    SET key = 'key', generation = 'generation'
    ON DUPLICATE KEY 
    UPDATE key = 'key', generation = (generation + 1)
    ;
    
  5. ==============================

    5.난 당신이 플랫폼 중립적 인 해결책을 찾기 위해려고하고 있다는 것을 모른다.

    난 당신이 플랫폼 중립적 인 해결책을 찾기 위해려고하고 있다는 것을 모른다.

    이것은 흔히 "UPSERT"라고합니다.

    일부 관련 토론을 참조하십시오 :

  6. ==============================

    6.PostgreSQL을 거기에 더 병합 명령 없으며, 실제로 그것을 작성하는 것은 사소한 아니다 - 작업이 "재미"만드는 이상한 가장자리 경우가 실제로있다.

    PostgreSQL을 거기에 더 병합 명령 없으며, 실제로 그것을 작성하는 것은 사소한 아니다 - 작업이 "재미"만드는 이상한 가장자리 경우가 실제로있다.

    (같이 : 가장 가능한 조건에서 작업) 최고 - 수동 (merge_db)에 표시된 것과 같은 접근 방식은 기능을 사용하는 것입니다.

    이 기능을 사용하지 않으려면, 당신은 일반적으로 멀리 얻을 수 있습니다 :

    updated = db.execute(UPDATE ... RETURNING 1)
    if (!updated)
      db.execute(INSERT...)
    

    그냥 증거 잘못되지 않는다는 것을 기억하고 결국 실패합니다.

  7. ==============================

    7.표준 SQL은이 작업의 MERGE 문을 제공합니다. 모든 DBMS는 MERGE 문을 지원합니다.

    표준 SQL은이 작업의 MERGE 문을 제공합니다. 모든 DBMS는 MERGE 문을 지원합니다.

  8. ==============================

    8.당신이 (트랜잭션을 통해 예를 들어) 원자 적으로 갱신 또는 삽입하는 일반적인 방법이없는 경우에 당신은 다른 잠금 방식으로 폴백 할 수 있습니다. 0 바이트 파일 시스템 뮤텍스, 명명 된 파이프, 등 ...

    당신이 (트랜잭션을 통해 예를 들어) 원자 적으로 갱신 또는 삽입하는 일반적인 방법이없는 경우에 당신은 다른 잠금 방식으로 폴백 할 수 있습니다. 0 바이트 파일 시스템 뮤텍스, 명명 된 파이프, 등 ...

  9. ==============================

    9.당신은 삽입 트리거를 사용할 수 있을까요? 실패하면, 갱신을한다.

    당신은 삽입 트리거를 사용할 수 있을까요? 실패하면, 갱신을한다.

  10. ==============================

    10.당신은 당신을 위해 SQL을 쓰는 라이브러리를 사용하여 함께있을 OK, 당신은 Upsert 사용할 수있는 경우 (현재 루비와 파이썬 만 해당) :

    당신은 당신을 위해 SQL을 쓰는 라이브러리를 사용하여 함께있을 OK, 당신은 Upsert 사용할 수있는 경우 (현재 루비와 파이썬 만 해당) :

    Pet.upsert({:name => 'Jerry'}, :breed => 'beagle')
    Pet.upsert({:name => 'Jerry'}, :color => 'brown')
    

    MySQL은, 포스트 그레스, 및 sqlite3를 통해 작동합니다.

    그것은 저장 프로 시저 또는 MySQL과 포스트 그레스에서 사용자 정의 기능 (UDF)를 기록한다. 이 INSERT를 사용 또는 sqlite3를에 교체.

  11. from https://stackoverflow.com/questions/690632/how-do-i-update-a-row-in-a-table-or-insert-it-if-it-doesnt-exist by cc-by-sa and MIT license