postgres 테이블의 각 레코드에 대해 트리거를 실행하는 좋은 방법이 있습니까?


22

Slony-I를 통해 복제 된 일부 테이블의 디자인을 제어 할 수없는 시스템이 있으므로 복제 테이블에서 일부 정보를 추출하는 '새도우 테이블'이라고하는 일련의 항목이 있습니다. 무시하고 싶은 레코드를 제거하면서 필요한 처리 된 양식으로 저장하십시오.

지금 새 복제본을 설정 한 후 업데이트 UPDATE tablename SET field=field를 실행하고 트리거를 강제로 실행하도록 값을 다시 설정 (예 :)하지만 일부 테이블은 수백만 개의 레코드로 커져서 30 분이 걸릴 수 있습니다. . (그리고 진공도 있습니다).

전달하는 더 좋은 방법이 있습니까, 또는 입력 된 입력으로 또는 NEW호출 컨텍스트에 따라 작동하도록 함수를 작성하는 방법이 있습니까? 하나가 업데이트되는 곳이 너무 많고 다른 부분이 아닌 곳을 두 번 보았으므로 두 가지 다른 기능을 유지하는 것을 꺼려합니다.


트리거를 실행하는 방법 을 알았습니다 ... 좋은 방법 이 있는지 물었 습니다.
— Joe

답변:


19

다음 템플릿을 사용하여 수행 할 수 있습니다.

CREATE TABLE tablename ( ... );

/* for direct invocation */
CREATE FUNCTION propagate_data(newrow tablename) RETURNS void
LANGUAGE plpgsql
AS $$
BEGIN
    INSERT INTO other_table VALUES (newrow.a, newrow.b, ...);
END:
$$;

/* trigger function wrapper */
CREATE FUNCTION propagate_data_trg() RETURNS trigger
LANGUAGE plpgsql
AS $$
BEGIN
    PERFORM propagate_data(NEW);
END;
$$;

CREATE TRIGGER propagate_data AFTER INSERT ON tablename FOR EACH ROW
    EXECUTE PROCEDURE propagate_data_trg();

Doh ... 나는 그것에 대해 거꾸로 생각하고있었습니다 (거의 기능을 비자가 아닌 절차로 호출 할 수 있도록하려고합니다).
— Joe

1
실제로 그것을 할 때 'row'가 예약어라는 것을 깨달았으므로 다른 사람들이 디버깅에 오래 걸리지 않도록 예제를 수정했습니다.
— Joe

1
몇 년 전에 정말 따라 왔어 야 했어요 시스템에서 모든 작업을 수행하기까지 시간이 조금 걸렸습니다 ...이 방법은 효과가 있지만 성능은 끔찍했습니다. (완료하기 위해 30 분에서 하루 이상으로 갔다).
— Joe
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.