2015-01-28 4 views
0

tab 테이블에 두 개의 열이 있습니다. col1col2입니다. 값이 X 인 경우 col1에 삽입 된 경우 해당 값이 col1이나 col2 (또는 그 반대) 중 어느 행에도 없어야합니다. 따라서 실제로 col1col2을 동일한 열로 취급하고 싶습니다 (고유성에 따라). 그것은 간단하게 보이지만 적절한 인덱스를 설정하는 방법을 알아낼 수 없습니다 ...고유 인덱스 - col1 또는 col2의 고유 값

+1

질문 : 어떤 유형의 데이터 인 경우 왜 같은 열에 저장하지 않으시겠습니까? 모든 배경 정보가 없으면 잘못된 데이터 모델처럼 들리지만 잘못된 것일 수 있습니다. –

+0

예 이건 이상하다고 생각하지만이 "비정규 화 된"데이터 모델이 필요합니다. 사실'col1','col2'는 "parent"나 "child"가없는 one-to-one 관계를 기술 할 것이므로 데이터는'(1,2)'또는'(2,1)'일지 모르지만' 1 '은'col1' 또는'col2'에서 발생합니다. 이것은 다른 행 (일대일)에 존재할 수 없습니다. – user606521

+1

필자는 여러분이 필요로하는 일종의 크로스 - 칼럼 참조 (cross-column referencing) 때문에 인덱스로이 작업을 수행 할 수 있을지 의심 스럽다. 'BEFORE INSERT' 트리거로 확실히 할 수 있습니다. – Patrick

답변

1

규칙이나 트리거를 사용할 수 있습니다. 이미 존재하는 값을 삽입하려고하면, 지금

create or replace rule check_uniqueness as on insert to tab where (check_value_exists(NEW.col1) OR check_value_exists(NEW.col2)) DO INSTEAD NOTHING; 

아무것도 : 그렇게 될 수

CREATE OR REPLACE FUNCTION check_value_exists(val ANYELEMENT) returns boolean as $$ 
select val IN (select col1 from tab union select col2 from tab) 
$$ 
LANGUAGE sql; 

그리고 규칙 : 편의를 위해 먼저 간단한 값이 이미 존재하는 경우 확인 기능을 필요가 없습니다 삽입 될 것입니다 (아무 것도 대신 사용하십시오).

당신은 값이 이미 존재하는 경우 (즉, 예외 또는 경고 또는 뭔가 다른 인상), 당신은 아마 더 나은 트리거 (조금 더 코드하지만 더 강력한)를 사용하는 경우를 처리 개선하려면 다음

CREATE OR REPLACE FUNCTION check_uniqueness() RETURNS TRIGGER AS $$ 
BEGIN 
    IF (check_value_exists(NEW.col1) OR check_value_exists(NEW.col2)) THEN 
    RAISE EXCEPTION 'Value % or % already exists',NEW.col1,NEW.col2; 
    END IF; 
    return NEW; 
    END; 
$$LANGUAGE plpgsql; 


CREATE TRIGGER check_uniqueness_trigger BEFORE INSERT ON tab FOR EACH ROW EXECUTE PROCEDURE check_uniqueness();