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.