2012-08-22 3 views
1

나는 합성 인덱스를 생성 한 타임 스탬프 필드가있는 테이블을 가지고 있습니다.테이블 (열) 대신 인덱스 이름을 기반으로 외래 키 만들기

CREATE INDEX "IDX_NAME_A" ON TABLE "A" (a_id, extract(year FROM created_at)) 

외래 키 관계를 갖고 싶은 연도와 a_id를 저장하는 다른 테이블이 있습니다.

내가 원하는 것을 수행하는 구문을 찾을 수없는 것 같습니다.

ALTER TABLE "B" 
    ADD FOREIGN KEY(a_id, a_year) 
    REFERENCES A(a_id, extract(YEAR FROM created_at)); 

는 생산 :

ERROR: syntax error at or near "(" 

나는 또한 시도했다 ...

ALTER TABLE "B" 
    ADD FOREIGN KEY(a_id, a_year) 
    USING INDEX "IDX_NAME_A"; 

어떤 아이디어?

Table A 
-------- 
a_id serial, 
created_at timestamp default now() 

Table B 
------- 
b_id serial 
a_id integer not null, 
a_year date_part('year') 
+0

어떻게'표 A'에 일년에 열을 추가하는 방법에 대한? – Kermit

답변

5

외래 키 제약 조건은 인덱스를 참조 할 수 없습니다. 그것은 테이블이어야합니다.
외래 키 제약 조건은 식을 참조 할 수 없습니다. 그것은 참조 된 테이블의 열 이름을 가리켜 야합니다.
그리고 참조 된 컬럼 세트에 고유 색인 (기본 키가 함축적으로 규정 됨)이 있어야합니다.

the manual about foreign keys here으로 시작하십시오.


뛰어난 디자인은 열 b.a_year을 삭제하는 것입니다. 100 % 중복되며 언제든지 a.created_at에서 파생 될 수 있습니다. (예를 테이블 b에서 특정 조건에 대한 연간 하나 개의 행을 적용하는) 당신이 긍정적으로 열을해야하는 경우

,이 같은 목표를 달성 할 수

@ 후 야유의 코멘트 업데이트
CREATE TABLE a (
    a_id serial 
,created_at timestamp NOT NULL DEFAULT now() 
,a_year NOT NULL DEFAULT extract(year FROM now())::int -- redundant, for fk 
,CHECK (a_year = extract(year FROM created_at)::int) 
); 

CREATE UNIQUE INDEX a_id_a_year_idx ON TABLE a (a_id, a_year); -- needed for fk 

CREATE TABLE b (
    b_id serial 
,a_id integer NOT NULL 
,a_year int -- doesn't have to be NOT NULL, but might 
,CONSTRAINT id_year FOREIGN KEY (a_id, a_year) REFERENCES a(a_id, a_year) 
); 

: 를 CHECK 열과 조합 된 제한은 DEFAULTNOT NULL 절을 사용하여 정권을 시행합니다.

또는 (이하 간단하지만 NULL 값을 허용하는) 당신이 trigger으로 a.a_year의 값을 유지할 수 :

CREATE OR REPLACE FUNCTION trg_a_insupbef() 
    RETURNS trigger AS 
$BODY$ 
BEGIN 

NEW.a_year := extract(year FROM NEW.created_at)::int; 
RETURN NEW; 

END; 
$BODY$ 
    LANGUAGE plpgsql VOLATILE; 

CREATE TRIGGER insupbef 
    BEFORE INSERT OR UPDATE ON a 
    FOR EACH ROW EXECUTE PROCEDURE trg_a_insupbef(); 
+2

c_year가 항상 created_at에있는 연도라고 가정하면, 그 것에 대해서도 CHECK 제약 조건을 추가 할 것입니다. –

+0

@Catcall : CHECK 제약 조건에 대한 좋은 조언! (질문과 일관되게하기 위해'a_year'로 이름이 바뀌 었습니다.) –

+0

잘 생각해 주셔서 감사합니다. 나는 실제로 created_at를 사용하지 않고, DEFAULT가 실패하도록하는 published_at (다른 컬럼의 값에 기반하여 디폴트를 설정할 수 없기 때문에)를 사용합니다. 에 게시 된 날짜는 임의의 날짜입니다. –