2010-06-25 1 views
3

중복없이 삽입하는 두 가지 방법을 알고 있습니다. 첫 번째는 WHERE NOT EXISTS 절 사용 :중복 된 행을 삽입하는 것을 피하기 위해 더 빠른 SQL 패턴은 무엇입니까?

INSERT INTO table_name (col1, col2, col3) 
SELECT %s, %s, %s 
WHERE NOT EXISTS (
    SELECT * FROM table_name AS T 
    WHERE T.col1 = %s 
     AND T.col2 = %s) 

다른하고있다을 LEFT JOIN :

INSERT INTO table_name (col1, col2, col3) 
SELECT %s, %s, %s 
FROM (SELECT %s, %s, %s) A 
LEFT JOIN table_name B 
ON B.COL1 = %s 
AND B.COL2 = %s 
WHERE B.id IS NULL 
LIMIT 1 

빨리 다른 것보다있는 것과 같은 일반적인 규칙이 있는가, 아니면 테이블에 의존 않습니다 ? 두 가지 방법보다 나은 다른 방법이 있습니까?

+0

첫 번째 예에서 SELECT *를 원하십니까? 모든 열을 선택 하시겠습니까? 일반적으로, 그렇게하지 않을 것이지만 나는 포스트 그레스 전문가가 아니다. – DOK

+0

EXPLAIN을 사용하여 쿼리를 실행하고 게시 할 수 있습니까? 분석 도구는 이러한 질문에 대한 답변을 제공합니다. – Freiheit

답변

5

고유해야하는 열 (이 경우 col1 & col2)에 대해 UNIQUE 제약 조건을 정의한 다음 INSERT를 수행하는 것이 좋습니다. 필요에 따라 예외를 처리하십시오. 롤백을 요구하는 예외에 대한 귀하의 의견을 다시


은, PostgreSQL을위한 솔루션은 예외가 발생할 수 삽입을 시도하기 전에 트랜잭션 세이브 포인트를 설정하는 것입니다. 예외가 발생하면 저장 점으로 롤백하십시오. 참조

: 내가 사용 생각

+0

나는 고유의 제약 조건을 이미 가지고있다. 그러나 위반되었을 때 나는 지금까지 전체 트랜잭션을 커밋하거나 롤백해야합니다. 내 거래는 여러 번 삽입해야하지만, 일부는 부분적으로 커밋하고 싶지 않습니다. 더 나은 방법으로 예외를 처리 할 수있는 방법이 있습니까? 커서/트랜잭션을 망칠 필요가 없습니다. (파이썬에서 sqlobject 또는 psycopg2로 처리) – Claudiu

+0

예 : * 예외를 잡으십시오 *. 중복 키 위반 인 경우 행이 이미 있음을 의미하기 때문에 무시할 수 있습니다. 다른 유형의 예외 인 경우 문제가 발생했을 수 있습니다 (예 : SQL 구문 오류, 디스크 용량 부족, 네트워크 연결 끊김). –

+0

예외를 잡아서 같은 커서로 다른 쿼리를 실행하려고하면'psycopg2.InternalError : 현재 트랜잭션이 중단되었습니다; 트랜잭션 블록의 끝까지 행동 무시하기 '또는 어떤 종류의 정렬 – Claudiu

-1

존재는 더 효율적입니다 당신이 이렇게 할 수있는!

if exists(select 1 from table_name where col1 = %s and col2 = %s) then 
    insert into table_name (col1, col2, col3) 
    select %s, %s, %s; 
end if; 

테스트 대상이다 EXISTS 사용 NOT EXISTS를 사용하여 약 50 배 더 빠릅니다.

다른 방법은 EXCEPT를 사용합니다.

INSERT INTO table_name (col1, col2, col3) 
SELECT %s, %s, %s 
except 
select col1, col2, col3 from table_name 

시험 중, EXCEPT를 사용하면 NOT EXISTS를 사용하면 약 3 배 빠릅니다.

관련 문제