2011-12-09 4 views
4

2 테이블 간의 일대 다 관계를 설정하는 방법을 찾고 있습니다. 테이블 구조는 아래에 설명되어 있지만 문제를 전혀 상관없는 모든 것을 남기려고했습니다.SQL과 일대일 관계 정의

objects에는 uuid이라는 열이 있습니다.

contents에는 content, object_uuidtimestamp이라는 3 개의 열이 있습니다.

기본적인 아이디어는 objects에 행을 삽입하고 데이터베이스에서 새 uuid을 얻는 것입니다. 이 uuidcontents의 모든 행에 대해 내용을 개체와 연결하는 데 사용됩니다.

지금 나는 그것을 적용 할 데이터베이스를 사용하려고 해요 :

    objects에서 contents 참조 행의 각 행 (외래 키가해야 할이)
  • objects의 어떤 행이없이 존재하지
  • 이상 a row in contents

이러한 제약 조건은 트랜잭션 커밋시 적용되어야합니다.

objects 테이블의 행을 쓸 때 contents에 행이 없기 때문에 일반적인 트리거가 도움이되지 않을 수 있습니다. Postgres는 트랜잭션이 끝날 때까지 지연 될 수있는 constraint triggers이라고합니다. 그것들을 사용할 수도 있지만 일상적인 사용을 목적으로하지 않는 일종의 내부 구조 인 것처럼 보입니다.

아이디어 또는 솔루션은 표준 SQL (선호) 또는 Postgres (버전은 중요하지 않음)와 함께 작동해야합니다. 모든 입력에 감사드립니다.

+0

"내용"의 기본 키는 {object_uuid, the_timestamp}입니까? BTW * 왜 * 별도의 "객체"테이블을 원하십니까? IMHO는 content-> object_uuid의 도메인으로 만 제공됩니다. BTW2 : 당신이 원하는 제약 조건을 규칙으로 구현할 수 있습니까? (허용되는 이유는 postgres에 특정한 것입니까?) 그러나 새로운 행 삽입시 "content"값을 제공하는 데 여전히 문제가 있습니다. (나는 now()가 the_timestamp의 초기화 자로 충분하다고 생각한다.) – wildplasser

+0

@wildplasser 여러 테이블을 사용하는 이유는 여러 개의 내용이있을 수 있고 실제 테이블에이 질문의 예제보다 많은 내용이 포함되어 있기 때문이다. 아래에 요약 된 솔루션은 문제를 해결했습니다. 시간 내 줘서 고마워. –

답변

2

주요 문제는 외래 키 제약 조건 외입니다. 아무 제약도 다른 테이블을 참조 할 수 없습니다.

가장 일반적인 방법은 조금 비정규 화하고 object에 해당 열을 참조하는 숫자가 포함 된 contents의 열을 포함하는 것입니다. 최신 상태로 유지하기위한 트리거를 만들 수 있습니다. 이 열을 업데이트 할 수있는 사람을 통해 일부 사용자 보안을 넣어하지 않는

contents_count INTEGER NOT NULL DEFAULT 0

은 깨지지 않을 것이다. 그러나 방아쇠로 방아쇠를 당긴다면 우발적 인 부패로 피하려고합니다.

편집 : 설명에 따라 CHECK 제약 조건은 연기 할 수 없습니다. 이 솔루션은 동일한 트랜잭션에서 더 많은 내용을 추가하려는 경우에도 모든 내용이 제거되면 오류가 발생합니다.

+0

CHECK 제약 조건은 링크에 따라 연기 할 수 없습니다. 그래서 필자는 스키마가 예제보다 복잡하고 내용 그룹을 허용하므로 필요한 수의 내용을 보유하기 위해'objects '에 열을 추가하고 하나의 열은 현재 존재하는 컨텐트 그룹의 수를 보유하게됩니다. 'contents'에 삽입하면'objects' 테이블에 실제 숫자가 업데이트됩니다. 고유 한 제약 조건과 함께'objects (uuid, actual)'에서'objects (uuid, required) '에 이르는 외래 키 제약 조건은 check 제약 조건을 대체 할 수 있습니다. 내용을 세는 당신의 아이디어는 문제를 해결했습니다. Thanks –

0

아마도 당신이 원하는 것은 조금 더 정상화하는 것입니다. 다른 테이블의 요소를 참조하는 세 번째 테이블이 필요합니다. 표 objects은 고유 한 uuid가 있어야하고 테이블 contents은 자체 uuid가 있으며 테이블 objects에 대한 참조가 없습니다. 세 번째 테이블에는 다른 두 테이블에 대한 참조 만 있어야하지만 기본 키는 두 참조의 조합입니다. 예를 들어, 테이블 objects의 uuid가 있고 그 uuid의 모든 내용을 원한다면 세 번째 테이블에 object_uuid 및 content_uuid 열이 있고 테이블 내용에 uuid라는 자체 직렬 열이 있다고 가정하면 쿼리는 다음과 같아야합니다. 같은 :

SELECT * FROM thirdtable,contents 
    WHERE thirdtable.content_uuid = contents.uuid AND thirdtable.object_uuid=34; 

은 그럼 당신은 모든 테이블

CREATE TRIGGER my_insert_trigger AFTER INSERT OR UPDATE ON contents 
    FOR EACH ROW EXECUTE PROCEDURE my_check_function(); 

에 삽입 트리거상의를 사용할 수있는 다음 기능 my_check_function()에서 세 번째 테이블에 존재하지 않는 objects의 모든 행을 삭제합니다. 내 대답을하는 동안 다른 누군가가 먼저 대답했다. 내 솔루션이 마음에 들면 my_check_function() 함수를 만들 수있다.

+0

'my_check_function'이 세 번째 테이블에 포함되어 있지 않기 때문에'objects' 테이블에 삽입하면 행이 다시 삭제됩니다. 문제는 두 번째 테이블에 삽입하기 전에 실행될 수 있으므로 일반 트리거를 사용할 수 없다는 것입니다. –