일부 SQL Server에는 INSERT
기본 / 고유 키 제약 조건을 위반할 경우 건너 뛰는 기능 이 있습니다. 예를 들어, MySQL은 INSERT IGNORE
입니다.
PostgreSQL 을 에뮬레이트 INSERT IGNORE
하고 ON DUPLICATE KEY UPDATE
사용 하는 가장 좋은 방법은 무엇입니까 ?
답변
업데이트를 시도하십시오. 존재하지 않는 행을 수정하지 않으면 삽입을 수행하십시오. 분명히, 당신은 거래 안에서 이것을합니다.
클라이언트 측에 여분의 코드를 넣지 않으려는 경우 함수로 래핑 할 수 있습니다. 또한 그 생각에서 매우 드문 경쟁 조건에 대한 루프가 필요합니다.
설명서에 이에 대한 예가 있습니다. http://www.postgresql.org/docs/9.3/static/plpgsql-control-structures.html , 맨 아래 오른쪽에 예 40-2.
일반적으로 가장 쉬운 방법입니다. 규칙을 사용하여 마술을 할 수는 있지만 훨씬 더 혼란 스러울 것입니다. 나는 그 기능에 대한 랩핑 접근법을 언젠가 추천합니다.
이것은 단일 행 또는 소수의 행 값에 적용됩니다. 하위 쿼리와 같이 많은 양의 행을 처리하는 경우 INSERT 및 UPDATE에 대한 쿼리를 두 개의 쿼리로 나누는 것이 가장 좋습니다 (물론 적절한 조인 / 하위 선택-기본을 작성할 필요가 없음) 두 번 필터)
답변
PostgreSQL 9.5에서는 MySQL이 몇 년 동안 사용해 온 것처럼 기본 기능입니다 .
INSERT … ON 충돌하지 않음 / 업데이트 ( “UPSERT”)
9.5는 “UPSERT”작업을 지원합니다. INSERT는 ON CONFLICT DO UPDATE / IGNORE 절을 승인하도록 확장되었습니다. 이 조항은 복제 위반이 발생할 경우 취할 대체 조치를 지정합니다.
…
새로운 구문의 추가 예 :
INSERT INTO user_logins (username, logins)
VALUES ('Naomi',1),('James',1)
ON CONFLICT (username)
DO UPDATE SET logins = user_logins.logins + EXCLUDED.logins;
답변
편집 : 워렌의 대답 을 놓친 경우 PG9.5에 기본적으로 적용됩니다. 업그레이드 시간!
Bill Karwin의 답변을 바탕으로 규칙 기반 접근 방식이 어떻게 보이는지 설명합니다 (동일한 DB의 다른 스키마에서 전송하고 다중 열 기본 키 사용).
CREATE RULE "my_table_on_duplicate_ignore" AS ON INSERT TO "my_table"
WHERE EXISTS(SELECT 1 FROM my_table
WHERE (pk_col_1, pk_col_2)=(NEW.pk_col_1, NEW.pk_col_2))
DO INSTEAD NOTHING;
INSERT INTO my_table SELECT * FROM another_schema.my_table WHERE some_cond;
DROP RULE "my_table_on_duplicate_ignore" ON "my_table";
참고 : INSERT
규칙은 규칙이 삭제 될 때까지 모든 작업에 적용 되므로 특별하지는 않습니다.
답변
Postgres 9.5 이상을 사용하는 사용자에게는 새로운 ON CONFLICT DO NOTHING 구문이 작동해야합니다.
INSERT INTO target_table (field_one, field_two, field_three )
SELECT field_one, field_two, field_three
FROM source_table
ON CONFLICT (field_one) DO NOTHING;
이전 버전을 사용하는 사람들에게는이 올바른 조인이 대신 작동합니다.
INSERT INTO target_table (field_one, field_two, field_three )
SELECT source_table.field_one, source_table.field_two, source_table.field_three
FROM source_table
LEFT JOIN target_table ON source_table.field_one = target_table.field_one
WHERE target_table.field_one IS NULL;
답변
인서트 무시 로직 을 얻으려면 다음과 같이 할 수 있습니다. 리터럴 값의 select 문에서 삽입하는 것이 가장 효과적이라는 것을 알았으므로 NOT EXISTS 절을 사용하여 중복 키를 마스킹 할 수 있습니다. 중복 논리에 대한 업데이트를 얻으려면 pl / pgsql 루프가 필요할 것으로 생각됩니다.
INSERT INTO manager.vin_manufacturer
(SELECT * FROM( VALUES
('935',' Citroën Brazil','Citroën'),
('ABC', 'Toyota', 'Toyota'),
('ZOM',' OM','OM')
) as tmp (vin_manufacturer_id, manufacturer_desc, make_desc)
WHERE NOT EXISTS (
--ignore anything that has already been inserted
SELECT 1 FROM manager.vin_manufacturer m where m.vin_manufacturer_id = tmp.vin_manufacturer_id)
)
답변
INSERT INTO mytable(col1,col2)
SELECT 'val1','val2'
WHERE NOT EXISTS (SELECT 1 FROM mytable WHERE col1='val1')
답변
PostgreSQL은 rule 이라는 스키마 객체를 지원하는 것 같습니다 .
http://www.postgresql.org/docs/current/static/rules-update.html
ON INSERT
주어진 테이블에 대한 규칙 을 만들어 NOTHING
주어진 기본 키 값 으로 행이 존재 UPDATE
하는 INSERT
경우 행을 만들거나 주어진 기본 키 값 으로 행이 존재 하는 경우 행을 대신 할 수 있습니다.
나는 이것을 직접 시도하지 않았으므로 경험에서 말하거나 예를 제시 할 수 없습니다.