2011-08-05 3 views
0

두 가지 유형의 이미지를 나타내는 두 개의 테이블이 있습니다. 나는 그 이미지의 경계를 표현하기 위해 PostGIS를 사용하고있다. I는 I가 서로 중첩 이미지의 모든 ID들을 포함 할 교차 참조 테이블을 갖고PostgreSQL 트리거 함수를 작성하는 데 도움이 필요합니다.

CREATE TABLE img_format_a (
    id SERIAL PRIMARY KEY, 
    file_path VARCHAR(1000), 
    boundary GEOGRAPHY(POLYGON, 4326) 
); 

CREATE TABLE img_format_p (
    id SERIAL PRIMARY KEY, 
    file_path VARCHAR(1000), 
    boundary GEOGRAPHY(POLYGON, 4326) 
); 

: 여기 테이블의 간략화 된 예이다. "A"유형의 이미지가 데이터베이스에 삽입 될 때마다 기존의 "P"유형의 이미지와 겹치는 지 (그리고 그 반대) 확인하고 해당 항목을 img_a_img_p 상호 참조 테이블에 삽입합니다. 이 테이블은 다 대 다 관계를 나타냄니다.

내 첫 번째 본능은이 img_a_img_p 테이블을 관리하기위한 트리거를 작성하는 것입니다. 나는 전에 방아쇠를 만든 적이 없으므로 이것이 바보 같은 짓인지 알려주세요. 그러나 그것은 나에게 의미가있는 것처럼 보입니다. 그래서 다음과 같은 방아쇠를 만듭니다.

CREATE TRIGGER update_a_p_cross_reference 
    AFTER INSERT OR DELETE OR UPDATE OF boundary 
    ON img_format_p FOR EACH ROW 
    EXECUTE PROCEDURE check_p_cross_reference(); 

방아쇠를 당기는 부분은 방아쇠 기능을 작성하는 것입니다. 내 코드는 Java이고 PL/pgSQL과 같은 도구가 있지만 사용해야하는 것이거나 특수 부가 기능 중 하나가 필요한 것인지 확실하지 않습니다.

기본적으로 새로운 이미지가 img_format_a 또는 img_format_p에 삽입 될 때마다 상호 참조 테이블을 업데이트해야한다는 트리거가 필요합니다. 새로운 이미지가 삽입되면 ST_Intersects 같은 PostGIS 함수를 사용하여 새 이미지가 다른 테이블의 이미지와 겹쳐 지는지 여부를 확인하고 싶습니다. ST_INTERSECTS이 true를 반환하는 각 이미지 쌍에 대해 두 이미지의 ID가 모두 img_a_img_p 인 새 항목을 삽입하고 싶습니다. 누군가가이 트리거 기능을 작성하는 방법을 알아낼 수 있습니까?

SELECT * FROM img_format_p P 
    WHERE ST_Intersects(A.boundary, P.boundary); 

for each match in selection { 
    INSERT INTO img_a_img_p VALUES (A.id, P.id); 
} 

답변

4

당신은 같은 종류의 PL/pgSQL의 기능에 일반적인 INSERT ... SELECT 관용구를 래핑 수 :

NEW
Data type RECORD; variable holding the new database row for INSERT/UPDATE operations in row-level triggers. This variable is NULL in statement-level triggers and for DELETE operations.

OLD
Data type RECORD; variable holding the old database row for UPDATE/DELETE operations in row-level triggers. This variable is NULL in statement-level triggers and for INSERT operations.

:

create function check_p_cross_reference() returns trigger as 
$$ 
begin 
    insert into img_a_img_p (img_a_id, img_p_id) 
    select a.id, p.id 
    from img_format_a, img_format_p 
    where p.id = NEW.id 
     and ST_Intersects(a.boundary, p.boundary); 
    return null; 
end; 
$$ language plpgsql; 

트리거는 두 개의 추가 변수 NEW and OLD이 여기에 몇 가지 의사입니다

NEW.id을 사용하면 새로운 img_format_p 값에 액세스 할 수 있습니다. 현재 (can't use the plain SQL) 언어 트리거의 경우 :

It is not currently possible to write a trigger function in the plain SQL function language.

그러나 PL/pgSQL은 매우 비슷합니다. 이것은 AFTER 삽입 트리거로 이해합니다 :

CREATE TRIGGER update_a_p_cross_reference 
AFTER INSERT 
ON img_format_p FOR EACH ROW 
EXECUTE PROCEDURE check_p_cross_reference(); 

삭제는 foreign key on img_a_img_p and a cascading delete으로 처리 할 수있다. 당신은뿐만 아니라 업데이 트에 대한 귀하의 트리거를 사용할 수 있습니다

CREATE TRIGGER update_a_p_cross_reference 
AFTER INSERT OR UPDATE OF boundary 
ON img_format_p FOR EACH ROW 
EXECUTE PROCEDURE check_p_cross_reference(); 

하지만 당신은 같은 뭔가 새로운 것들을 삽입하기 전에 이전 항목을 지우려면 아마 것 다음 INSERT...SELECT 문 앞에

delete from img_a_img_p where img_p_id = NEW.id; 

.

+0

와우, 정말 멋지고 자세한 대답에 감사드립니다. 감사합니다! – Steph

+0

트리거 함수를 실행하면 다음 오류가 발생합니다.'오류 : 구문 오류 또는 "근처에"''LINE 3 : img_a_img_p (img_a_id, img_p_id)에 삽입 '. 왜 내가 이걸 얻을 수 있을지 아십니까? PL/pgSQL은 기본적으로 공간 데이터베이스에 설치되어야합니다. 이 오류를 이해하는 데 문제가 있습니다. – Steph

+0

@Steph : 절차에서 "시작"을 놓 쳤기 때문입니다 (새로운 세 번째 줄 참조). 미안 해요, 방금 테스트하지 않고 머리 꼭대기에서 썼습니다. –

관련 문제