2013-06-09 3 views
0

에 삽입 예상대로 나는 테이블의 또 다른PostgreSQL의 기능이

$BODY$ 
    BEGIN 
      INSERT INTO backups.calls2 (uid,queue_id,connected,callerid2) 
      SELECT distinct (c.uid) ,c.queue_id,c.connected,c.callerid2 
      FROM public.calls c 
      WHERE c.connected is not null; 
     RETURN; 
    EXCEPTION WHEN unique_violation THEN NULL; 
    END; 
$BODY$ 

그리고 구조에 하나 개의 테이블에서 데이터를 삽입하는 기능이 작동하지 :

내가 처음이 쿼리를 실행 한
CREATE TABLE backups.nc_calls_id 
(
    uid character(30) NOT NULL, 
    queue_id integer, 
    callerid2 text, 
    connected timestamp without time zone, 
    id serial NOT NULL, 
    CONSTRAINT calls2_pkey PRIMARY KEY (uid) 
) 
WITH (
    OIDS=FALSE 
); 

, 모든 것이 정상적으로 진행되었습니다. 200000 개의 행이 고유 ID가있는 새 테이블에 삽입되었습니다. 하지만 다시 실행하면 행이 삽입되지 않습니다.

+1

uid의 값이 반복되는지 확인 했습니까? – Satya

+0

그들은 고유합니다 – ssuperczynski

+0

DISTINCT와 DISTINCT ON은 두 가지 다른 기능입니다. 어느 쪽이 필요합니까? SER에 무슨 일이 일어나고 있는지에 대한 예외 상황에서 RAISE INFO를 사용하십시오. –

답변

3

제공된 PostgreSQL 버전이 없으며 params 등을 표시하는 CREATE FUNCTION 문이 없으며 다른 테이블 구조도없고 함수 호출도 없습니다.) 나는 추측하고 있습니다. 병합을 시도하는 중입니다. 행이 이미 존재하면 행을 건너 뜀으로써 행이 존재하지 않는 경우에만 행을 삽입합니다.

행이 이미있는 경우 위의 기능을 수행하면 모든 행이 건너 뜁니다.

BEGIN ... EXCEPTION 블록 (느림) 또는 LOCK 블록 내에서 삽입을 수행하려면 루프를 사용하고 INSERT INTO ... SELECT ... FROM newtable WHERE NOT EXISTS (SELECT 1 FROM oldtable where oldtable.key = newtable.key)을 수행해야합니다.

INSERT INTO ... SELECT ... WHERE NOT EXISTS 메서드는 훨씬 더 잘 수행되지만 동시에 둘 이상이 실행되거나 다른 대상이 동시에 대상 테이블에 삽입되면 실패합니다. 목적지 테이블을 실행하기 전에 목적지 테이블이 안전한지 확인하십시오.

PL/PgSQL 루핑 BEGIN ... EXCEPTION 방법 소리 얼핏보기에 안전하고 안전합니다. 그런 다음 한 번에 두 개를 실행하면 어떻게되는지 생각해보십시오. 하나는 몇 개의 키를 먼저 삽입 할 것이고 다른 하나는 다른 키를 먼저 삽입 할 것입니다. 그래서 그들 사이에 값의 분할이 있습니다. 그건 괜찮아요, 함께 그들은 전체 집합을 구성합니다. 하지만 그 중 하나만 커밋하고 다른 하나는 어떤 이유로 실패하면 어떻게 될까요? 재미있게 삽입 된 결과가 나타납니다. 따라서이 접근법을 사용하는 경우 대상 테이블을 잠그는 것이 가장 좋습니다. 서브 쿼리 기반 고유성 위반 검사와 함께 훨씬 효율적인 단일 패스 INSERT을 사용할 수도 있습니다.

+0

예, 이것이 내가 찾고있는 것입니다. 하지만 LOOP – ssuperczynski

+0

@infaustus로 쓰는 방법을 모르겠다. NOT EXISTS를 사용하는 것이 더 빠르고 더 좋은 옵션이라고 생각한다. 루프를 사용하면 데이터가 커짐에 따라 함수가 더 길고 길어질 수 있습니다. – vyegorov

+0

@vyegorov 완전히 동의합니다. 'SAVEPOINT' ('BEGIN ... EXCEPTION' 블록에 의해 후드에서 사용되는)은 이전보다 훨씬 저렴합니다. 아직 사용하지 않는 것이 좋습니다. 저장 점의 비용 외에도 모든 항목을 효율적으로 일괄 처리하는 대신 개별 삽입 및 색인 조회에 드는 비용이 있습니다. –