IT

postgresql을 사용하여“insert ignore”및“replication key update”(sql merge)를 에뮬레이트하는 방법은 무엇입니까?

lottoking 2020. 7. 7. 07:26
반응형

postgresql을 사용하여“insert ignore”및“replication key update”(sql merge)를 에뮬레이트하는 방법은 무엇입니까?


일부 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규칙은 규칙이 삭제 될 때까지 모든 작업에 적용 되므로 특별하지는 않습니다.


인서트 무시 로직 을 얻으려면 다음과 같이 할 수 있습니다. 리터럴 값의 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)
)

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;

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

You could create a rule ON INSERT for a given table, making it do NOTHING if a row exists with the given primary key value, or else making it do an UPDATE instead of the INSERT if a row exists with the given primary key value.

I haven't tried this myself, so I can't speak from experience or offer an example.


As @hanmari mentioned in his comment. when inserting into a postgres tables, the on conflict (..) do nothing is the best code to use for not inserting duplicate data.:

query = "INSERT INTO db_table_name(column_name)
         VALUES(%s) ON CONFLICT (column_name) DO NOTHING;"

The ON CONFLICT line of code will allow the insert statement to still insert rows of data. The query and values code is an example of inserted date from a Excel into a postgres db table. I have constraints added to a postgres table I use to make sure the ID field is unique. Instead of running a delete on rows of data that is the same, I add a line of sql code that renumbers the ID column starting at 1. Example:

q = 'ALTER id_column serial RESTART WITH 1'

If my data has an ID field, I do not use this as the primary ID/serial ID, I create a ID column and I set it to serial. I hope this information is helpful to everyone. *I have no college degree in software development/coding. Everything I know in coding, I study on my own.


This solution avoids using rules:

BEGIN
   INSERT INTO tableA (unique_column,c2,c3) VALUES (1,2,3);
EXCEPTION 
   WHEN unique_violation THEN
     UPDATE tableA SET c2 = 2, c3 = 3 WHERE unique_column = 1;
END;

but it has a performance drawback (see PostgreSQL.org):

A block containing an EXCEPTION clause is significantly more expensive to enter and exit than a block without one. Therefore, don't use EXCEPTION without need.


On bulk, you can always delete the row before the insert. A deletion of a row that doesn't exist doesn't cause an error, so its safely skipped.


For data import scripts, to replace "IF NOT EXISTS", in a way, there's a slightly awkward formulation that nevertheless works:

DO
$do$
BEGIN
PERFORM id
FROM whatever_table;

IF NOT FOUND THEN
-- INSERT stuff
END IF;
END
$do$;

참고URL : https://stackoverflow.com/questions/1009584/how-to-emulate-insert-ignore-and-on-duplicate-key-update-sql-merge-with-po

반응형