2012-04-09 2 views
13

두 개의 테이블로 된 책과 오디오 북이 있는데, 둘 다 ISBN을 기본 키로 사용합니다. 책 및 오디오 북 ISBN에 외래 키 제약 조건이있는 isbn 특성을 가진 테이블이 writtenby 있습니다. writtenby에 삽입 할 때 발생하는 문제는 postgresql이 서적과 서적 모두에 삽입 된 ISBN을 원한다는 것입니다. 필자가 만든 저자와 책/오디오 북을 저장하는 테이블을 쓰는 것이 나에게 의미가 있지만, postgresql의 테이블로는 변환되지 않는다. 구현을 생각하고있는 대안 솔루션 인 audiobook_writtenby와 books_writtenby라는 두 가지 새로운 관계가 있었지만 이것이 좋은 대안인지 확신 할 수 없습니다. 두 개의 다른 테이블을 참조하여 하나의 테이블을 쓰는 방법을 생각해 보거나 데이터베이스를 더 잘 디자인 할 수있는 방법에 대한 아이디어를 어떻게 얻을 수 있습니까? 더 많은 정보가 필요하면 알려주세요.POSTGRESQL 외래 키 두 개의 서로 다른 테이블의 기본 키를 참조합니다.

답변

4

RDBMS는 다형 외래 키 제약 조건을 지원하지 않습니다. ORM 시스템을 만들 때 관계형 모델과 객체 관계형 임피던스 불일치의 실제 문제 중 하나에 의해 잘 수용되는 것은 합리적입니다. Nice discussion on this on Ward's WIki

Books and AudioBooks에서 별도의 테이블 known_isbns를 만들고 제약 조건 및/또는 트리거를 설정하여 테이블에 두 유형별 책 테이블의 모든 유효한 isbns가 포함되도록하는 것이 좋습니다. 그런 다음 writtenby에 대한 FK 제약 조건을 known_isbns와 비교합니다.

+3

관계형 모델과 SQL 데이터베이스는 실제로 이러한 종류의 문제를 잘 처리합니다. 문제는 관계형 또는 SQL이 아닙니다. 문제는 명백한 제약 조건 중 하나가 잘못 구현된다는 것입니다. (제한 사항은 서적과 오디오 북용 ISBN이 동일한 도메인에서 가져온 것임을 나타냅니다.) –

3

테이블 상속을 사용하면 두 가지 장점을 모두 활용할 수 있습니다. writtenby 테이블을 참조하여 INHERITS 절을 사용하여 audiobook_writtenby 및 books_writtenby를 만듭니다. 설명하는대로 외래 키를 하위 수준에서 정의 할 수 있지만 상위 수준에서 여전히 데이터를 참조 할 수 있습니다. (당신은 또한 볼 수있는이 작업을 수행 할 수 있지만 상속이 경우 청소기있을 것 같은데.)

는 문서를 참조하십시오 :

http://www.postgresql.org/docs/current/interactive/sql-createtable.html

http://www.postgresql.org/docs/current/interactive/tutorial-inheritance.html

http://www.postgresql.org/docs/current/interactive/ddl-inherit.html

을 이렇게하면 BEFORE INSERT 트리거를 writtenby 테이블에 추가 할 수 있습니다.

26

PostgreSQL에서이 작업을 수행하는 방법은 여러 가지가 있습니다. 개인적으로 나는이 방법을 선호한다.

-- This table should contain all the columns common to both 
-- audio books and printed books. 
create table books (
    isbn char(13) primary key, 
    title varchar(100) not null, 
    book_type char(1) not null default 'p' 
    check(book_type in ('a', 'p')), 
    -- This unique constraint lets the tables books_printed and books_audio 
    -- target the isbn *and* the type in a foreign key constraint. 
    -- This prevents you from having an audio book in this table 
    -- linked to a printed book in another table. 
    unique (isbn, book_type) 
); 

-- Columns unique to printed books. 
create table books_printed (
    isbn char(13) primary key references books (isbn), 
    -- Allows only one value. This plus the FK constraint below guarantee 
    -- that this row will relate to a printed book row, not an audio book 
    -- row, in the table books. The table "books_audio" is similar. 
    book_type char(1) default 'p' 
    check (book_type = 'p'), 
    foreign key (isbn, book_type) references books (isbn, book_type), 
    other_columns_for_printed_books char(1) default '?' 
); 

-- Columns unique to audio books. 
create table books_audio (
    isbn char(13) primary key references books (isbn), 
    book_type char(1) default 'a' 
    check (book_type = 'a'), 
    foreign key (isbn, book_type) references books (isbn, book_type), 
    other_columns_for_audio_books char(1) default '?' 
); 

-- Authors are common to both audio and printed books, so the isbn here 
-- references the table of books. 
create table book_authors (
    isbn char(13) not null references books (isbn), 
    author_id integer not null references authors (author_id), -- not shown 
    primary key (isbn, author_id) 
); 
-1

이 예제에서는 여러 테이블을 사용할 필요가 전혀 없습니다. 해당되는 경우 표 "Book"을 사용하고 "AudioBook"의 열을 추가하십시오. 특정 열이있는 테이블 수준에서 구별해야하는 경우보기를 만듭니다. 같은 내용의 "서적"과 "오디오 북"에 동일한 ISBN이 있는지 확인 했습니까?

+2

답변이 기술적으로 정확하더라도 나는 따라야한다고 생각하지 않습니다. PostgreSQL은 이것을 깔끔하게 모델링 할 수 있습니다. 여러 객체를 하나의 테이블로 접는 것은 일반적으로 큰 혼란에 처하게됩니다. – Theuni

관련 문제