[SQL] 어떻게 동적으로 PostgreSQL의 8.2 TG_TABLE_NAME를 사용 하는가?
SQL어떻게 동적으로 PostgreSQL의 8.2 TG_TABLE_NAME를 사용 하는가?
동적으로 생성하고 SQL 문을 실행하는 TG_TABLE_NAME를 사용 PostgreSQL의 8.2 트리거 함수를 작성하려합니다. 나는 PostgreSQL의 이후 버전에 대한 예는 모든 종류의를 찾을 수 있습니다,하지만 난 때문에 몇 가지 요구 사항 8.2에 붙어입니다. 그것은 작동하지만, 거의 동적 인 의미로 여기 내 기능은 다음과 같습니다
CREATE OR REPLACE FUNCTION cdc_TABLENAME_function() RETURNS trigger AS $cdc_function$
DECLARE
op cdc_operation_enum;
BEGIN
op = TG_OP;
IF (TG_WHEN = 'BEFORE') THEN
IF (TG_OP = 'UPDATE') THEN
op = 'UPDATE_BEFORE';
END IF;
INSERT INTO cdc_test VALUES (DEFAULT,DEFAULT,op,DEFAULT,DEFAULT,OLD.*);
ELSE
IF (TG_OP = 'UPDATE') THEN
op = 'UPDATE_AFTER';
END IF;
INSERT INTO cdc_test VALUES (DEFAULT,DEFAULT,op,DEFAULT,DEFAULT,NEW.*);
END IF;
IF (TG_OP = 'DELETE') THEN
RETURN OLD;
ELSE
RETURN NEW;
END IF;
END;
이 현재 작성 방법, 나는 모든 테이블에 대해 별도의 트리거 함수를 작성해야합니다. 동적으로 내 INSERT 문을 작성하고 단지로 접두사 TG_TABLE_NAME을 사용하고자하는 'cdc_'모든 테이블이 같은 명명 규칙을 따라야하기 때문이다. 그럼 내가 모든 테이블 호출 한 함수에 대한 모든 트리거를 가질 수 있습니다.
해결법
-
==============================
1.나는 몇 년 다시 똑같은 일을 찾고 있었다. 하나의 트리거 그들 모두를 지배하는 기능! 나는, 유즈넷 목록에 요청 아무 소용, 다양한 접근을 시도했다. 이 문제에 대한 합의가이 작업을 수행 할 수 없습니다이었다. PostgreSQL의 8.3 또는 그 이상의 단점.
나는 몇 년 다시 똑같은 일을 찾고 있었다. 하나의 트리거 그들 모두를 지배하는 기능! 나는, 유즈넷 목록에 요청 아무 소용, 다양한 접근을 시도했다. 이 문제에 대한 합의가이 작업을 수행 할 수 없습니다이었다. PostgreSQL의 8.3 또는 그 이상의 단점.
PostgreSQL의 8.4 이후 당신은 할 수 있습니다 :
EXECUTE 'INSERT INTO ' || TG_RELID::regclass::text || ' SELECT ($1).*' USING NEW;
페이지 8.2을 사용하면 문제가있다 :
시스템의 모든 테이블 이름은 같은 이름의 복합 형 역할을 할 수 있습니다. 따라서 당신은 매개 변수로 NEW / OLD을받는 함수를 작성하고 실행할 수 있습니다. 동적으로 생성하고 모든 트리거 이벤트에 해당 기능을 파괴 할 수있다 :
트리거 기능 :
CREATE OR REPLACE FUNCTION trg_cdc() RETURNS trigger AS $func$ DECLARE op text := TG_OP || '_' || TG_WHEN; tbl text := quote_ident(TG_TABLE_SCHEMA) || '.' || quote_ident(TG_TABLE_NAME); cdc_tbl text := quote_ident(TG_TABLE_SCHEMA) || '.' || quote_ident('cdc_' || TG_TABLE_NAME); BEGIN EXECUTE 'CREATE FUNCTION f_cdc(n ' || tbl || ', op text) RETURNS void AS $x$ BEGIN INSERT INTO ' || cdc_tbl || ' SELECT op, (n).*; END $x$ LANGUAGE plpgsql'; CASE TG_OP WHEN 'INSERT', 'UPDATE' THEN PERFORM f_cdc(NEW, op); WHEN 'DELETE' THEN PERFORM f_cdc(OLD, op); ELSE RAISE EXCEPTION 'Unknown TG_OP: "%". Should not occur!', TG_OP; END CASE; EXECUTE 'DROP FUNCTION f_cdc(' || tbl || ', text)'; IF TG_OP = 'DELETE' THEN RETURN OLD; ELSE RETURN NEW; END IF; END $func$ LANGUAGE plpgsql;
방아쇠:
CREATE TRIGGER cdc BEFORE INSERT OR UPDATE OR DELETE ON my_tbl FOR EACH ROW EXECUTE PROCEDURE trg_cdc();
표 이름은 사용자 입력처럼 처리해야한다. 사용에서 quote_ident ()는 SQL 주입에 대한 방어.
그러나,이 방법은 생성하고 모든 단일 트리거 이벤트에 대한 기능을 놓습니다. 꽤 오버 헤드, 나는 그것을 위해 갈 것이다. 당신은 어떤 카탈로그 테이블을 많이 진공 청소기로 청소해야합니다.
PostgreSQL는 함수 오버로드를 지원한다. 따라서, 동일한 기본 이름 (그러나 다른 유형 파라미터)의 테이블 당 하나 개의 기능이 공존 할 수있다. 당신은 중간을 극적으로 당신이 방아쇠를 만들 때와 같은 시간에 테이블 당 한 번 f_cdc (..)를 생성하여 소음을 줄일 수 있습니다. 즉, 테이블 당 하나 개의 작은 기능입니다. 당신은 테이블 정의의 변화를 관찰해야하지만, 테이블은 자주 변경하지 않아야합니다. 빠르고 우아한 트리거, 작은 도착, CREATE 및 트리거 기능에서 DROP 기능 제거합니다.
나 자신은 8.2 PG에서 그 일을 볼 수 있었다. 나 자신이 더 이상 페이지 8.2에서 아무것도 볼 수 있다는 점을 제외하고. 그것은 어쩌면 당신은 결국 어떻게 든 업그레이드 할 수 있습니다 2011 년 12 월 삶의 끝에 도달했습니다.
-
==============================
2.또한 몇 년 전에 비슷한 질문을했다.
또한 몇 년 전에 비슷한 질문을했다.
그것은 당신에게 유용한 아이디어를 제공하면 그 질문에 살펴보고 참조 :
삽입 NEW. *에서 PL / pgSQL의 EXECUTE 사용하여 일반 트리거에서
from https://stackoverflow.com/questions/7519044/how-to-dynamically-use-tg-table-name-in-postgresql-8-2 by cc-by-sa and MIT license
'SQL' 카테고리의 다른 글
[SQL] 마이크로 소프트 액세스 2010 .accdb에 대한 SQL 연결 문자열 (0) | 2020.06.13 |
---|---|
[SQL] MS Access에서 CONCAT 동등한 (0) | 2020.06.13 |
[SQL] MySQL 데이터베이스에서 PHP의 모든 테이블 이름을 표시 (0) | 2020.06.13 |
[SQL] 인덱스 스캔의 선택도의 역할 / 구 (0) | 2020.06.13 |
[SQL] 마이크로 소프트 액세스 - 케이스 쿼리 (0) | 2020.06.13 |