두 테이블 MySQL의 상속을 모델링하는 방법


14

데이터를 저장하는 event테이블 이 있고 테이블 에 저장하려는 작업을 수행 한 사람의 유형 (작업자, 시민)에 따라 이제이 사람들이 동물을 구출합니다 ( animal테이블이 있습니다).

마지막으로, 남자 (작업자, 시민)가 동물을 구한 사건을 보관할 테이블을 갖고 싶지만 외래 키를 추가해야 id합니까?

이제이 디자인에서 나는 어떤 사람이 일을했는지 ​​관계를 알지 못합니다. 일종의 사람 (일명 민사)만이 마지막 테이블 civil_idperson열에 만 값을 저장 하려고합니다 ... 그것이 민간인인지 근로자인지 아는 경우 다른 "중급"테이블이 필요합니까?

MySQL에서 다음 다이어그램의 디자인을 반영하는 방법은 무엇입니까?

여기에 이미지 설명을 입력하십시오

추가 세부 사항

나는 그것을 다음과 같이 모델링했다.

DROP    TABLE IF EXISTS `tbl_animal`; 
CREATE TABLE `tbl_animal` (
    id_animal       INTEGER     NOT NULL PRIMARY KEY AUTO_INCREMENT,
    name            VARCHAR(25) NOT NULL DEFAULT "no name",
    specie          VARCHAR(10) NOT NULL DEFAULT "Other",
    sex             CHAR(1)     NOT NULL DEFAULT "M",
    size            VARCHAR(10) NOT NULL DEFAULT "Mini",
    edad            VARCHAR(10) NOT NULL DEFAULT "Lact",
    pelo            VARCHAR(5 ) NOT NULL DEFAULT "short",
    color           VARCHAR(25) NOT NULL DEFAULT "not defined",
    ra              VARCHAR(25) NOT NULL DEFAULT "not defined",
    CONSTRAINT `uc_Info_Animal` UNIQUE (`id_animal`)           
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;


INSERT INTO `tbl_animal` VALUES (1,'no name', 'dog', 'M','Mini','Lact','Long','black','Bobtail');
INSERT INTO `tbl_animal` VALUES (2,'peluchin', 'cat', 'M','Mini','Lact','Long','white','not defined');
INSERT INTO `tbl_animal` VALUES (3,'asechin', 'cat', 'M','Mini','Lact','Corto','orange','not defined');

DROP    TABLE IF EXISTS `tbl_person`;  
CREATE TABLE `tbl_person` (
    type_person  VARCHAR(50) NOT NULL primary key        
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;
INSERT INTO `tbl_person` (type_person) VALUES ('Worker');
INSERT INTO `tbl_person` (type_person) VALUES ('Civil');



DROP    TABLE IF EXISTS `tbl_worker`;  
CREATE TABLE `tbl_worker`(
    id_worker           INTEGER  NOT NULL PRIMARY KEY,
    type_person         VARCHAR(50) NOT NULL , 
    name_worker         VARCHAR(50) NOT NULL ,    
    address_worker      VARCHAR(40) NOT NULL DEFAULT "not defined",     
    delegation          VARCHAR(40) NOT NULL DEFAULT "not defined",
    FOREIGN KEY (type_person)               REFERENCES `tbl_person` (type_person),
    CONSTRAINT `uc_Info_worker` UNIQUE (`id_worker`)           
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

INSERT INTO `tbl_worker` VALUES (1,'Worker','N_CEDENTE1', 'DIR Worker 1', 'DEL');
INSERT INTO `tbl_worker` VALUES (2,'Worker','N_worker1', 'DIR Worker 2', 'DEL');
INSERT INTO `tbl_worker` VALUES (3,'Worker','N_worker2', 'address worker','delegation worker'); 


DROP    TABLE IF EXISTS `tbl_civil`; 
CREATE TABLE `tbl_civil`(
    id_civil                        INTEGER  NOT NULL PRIMARY KEY,
    type_person         VARCHAR(50) NOT NULL ,
    name_civil                      VARCHAR(50)  ,
    procedence_civil                VARCHAR(40)  NOT NULL DEFAULT "Socorrism",    
  FOREIGN KEY (type_person)             REFERENCES `tbl_person` (type_person),
    CONSTRAINT `uc_Info_civil` UNIQUE (`id_civil`)           
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;


INSERT INTO `tbl_civil`  VALUES (1,'Civil','N_civil1' , 'Socorrism');


CREATE TABLE `tbl_event` (
    id_event     INTEGER NOT NULL,
    id_animal    INTEGER NOT NULL,
    type_person  VARCHAR(50) NOT NULL , 
    date_reception DATE DEFAULT '2000-01-01 01:01:01',
    FOREIGN KEY (id_animal)   REFERENCES `tbl_animal`    (id_animal),
    FOREIGN KEY (type_person )  REFERENCES `tbl_person`   (type_person ),
    CONSTRAINT `uc_Info_ficha_primer_ingreso` UNIQUE (`id_animal`,`id_event`)     
)ENGINE=InnoDB  DEFAULT CHARSET=utf8;

INSERT INTO `tbl_event` VALUES (1,1, 'Worker','2013-01-01 01:01:01' );
INSERT INTO `tbl_event` VALUES (2,2, 'Civil','2013-01-01 01:01:01' );

그러나 null을 제거하는 방법이 있습니까?

내가 가진 질문은 다음과 같습니다.

SELECT  a.*,b.*,z.*
FROM    tbl_event a
        left JOIN tbl_worker b
            ON a.type_person = b.type_person
        left JOIN tbl_animal z
            ON   z.id_animal = a.id_animal ;

SELECT  a.*,b.*,z.*
FROM    tbl_event a
        left JOIN tbl_civil b
            ON a.type_person = b.type_person
        left JOIN tbl_animal z
            ON   z.id_animal = a.id_animal ;

다음은 업데이트 된 sqlfiddle 입니다.


TYPE_PERSON하나의 열만 포함 하는 테이블의 목적은 무엇 입니까?
JW 웃


@cMinor-당신은 "일을 한 시민 또는 노동자의 ID를 아는 방법"을 묻습니다. 실생활에서 누가 그 일을했는지 ​​알고 있습니까 (혹은 숙제라면 상상력이 있습니까)? 충분한 소스 데이터가 있습니까?

나는 상속에 익숙해 져서 사람들의 유형 (노동자, 시민)을 담을 테이블 사람을 만든 다음 이벤트 테이블에서 직업 (민간 또는 노동자)이 어떻게 일했는지에 따라 사람을 참조하는 방법을 만들었습니까?
cMinor

1
데이터베이스 관리자
Pieter Geerkens

답변:


13

다이어그램을 만들었으므로 대답하는 것이 좋습니다.)

현재 관계형 데이터베이스는 불행히도 상속을 직접 지원하지 않으므로 "일반"테이블로 변환해야합니다. 이를위한 일반적으로 3 가지 전략이 있습니다.

  1. NULL이 아닌 공통 필드가있는 단일 테이블의 모든 클래스 1
  2. 별도의 테이블에 구체적인 클래스 2 가 있습니다. 추상 클래스에는 자체 테이블이 없습니다.
  3. 별도의 테이블에있는 모든 클래스

이것이 실제로 의미하는 것과 일부 장단점에 대한 자세한 내용은 원래 게시물에 제공된 링크를 참조하십시오. 그러나 간단히 다른 두 가지 이유 중 하나가 없으면 (3)이 기본값이되어야합니다. 다음과 같이 데이터베이스에서 (3)을 나타낼 수 있습니다.

CREATE TABLE person (
    person_id int PRIMARY KEY
    -- Other fields...
);

CREATE TABLE civil (
    civil_id int PRIMARY KEY REFERENCES person (person_id)
    -- Other fields...
);

CREATE TABLE worker (
    worker_id int PRIMARY KEY REFERENCES person (person_id)
    -- Other fields...
);

CREATE TABLE event (
    event_id int PRIMARY KEY,
    person_id int REFERENCES person (person_id)
    -- Other fields...
);

불행하게도,이 구조는 당신이해야 할 것입니다 person둘 다되는 civilworker(즉, 당신이 추상 클래스를 인스턴스화 할 수 있습니다), 또한 당신이 만들 수있는 것 person입니다 모두 civilworker. 데이터베이스 수준에서 전자를 적용 할 수있는 방법이 있으며 연기 된 제약 조건을 지원하는 DBMS 3 도 후자가 데이터베이스 내에서 시행 될 수 있지만 실제로는 응용 프로그램 수준 무결성을 사용하는 것이 바람직 할 수있는 몇 안되는 경우 중 하나입니다 .


1 person , civilworker,이 경우이다.

(2) civilworker(이 경우 person"추상적"입니다).

3 어떤 MySQL은 그렇지 않습니다.


지연된 제약 조건을 지원하는 DBMS에서 후자를 어떻게 적용 할 수 있습니까? ( civil및 사람이되는 것을 금지 worker)
Gima

@Gima 답변에 제공 한 링크를 따르십시오.
Branko Dimitrijevic

현재 관계형 데이터베이스는 상속을 지원하지 않는다고 주장합니다. postgresql은 어떻습니까? postgresql.org/docs/9.6/static/ddl-inherit.html
Climax

@Climax PostgreSQL을 알고 있지만 구현은 부분적입니다. 귀하의 링크에서 : "제약 (독특한, 기본 키 및 외래 키 제약) 다른 유형의 상속되지 않습니다."
Branko Dimitrijevic

1
@naaz 외래 키는 모두 civil와에 worker있습니다. 아마 당신은 (단지 짧은 손 구문 놓친 REFERENCES하지를 FOREIGN KEY)?
Branko Dimitrijevic

5

고유 한 Civil_ID 및 Worker_ID가 필요하지 않습니다. Person, Civil 및 Worker의 세 가지 테이블 모두에서 Person-ID를 계속 키로 사용하십시오. "Civil"및 "Worker"라는 두 값을 사용하여 Person에 열 PersonType을 추가하십시오.

이것은 이제 기본 엔티티 Person의 하위 엔티티 Civil 및 Worker로 추상 기본 클래스 PersonClass의 두 개의 서브 클래스 CivilClass 및 WorkerClass를 나타냅니다. DB의 데이터 모델과 응용 프로그램의 객체 모델이 잘 일치합니다.


sqlfiddle sqlfiddle.com/#!2/1f6a4/1 을 수행 했지만 다른 테이블에 참여하는 방법을 모르겠습니다. 여기 sqlfiddle에서 답변을 알려주시겠습니까?
cMinor

아무 "별개"입니다 civil_idworker_id- 그들은 같은 일이 있습니다 person_id만 다른 이름, - 상기 보면 FK1그들의 앞에 (외래 키) 마커.
Branko Dimitrijevic

4

귀하의 사례는 클래스 / 하위 클래스 모델링의 인스턴스입니다. 또는 응급실, 일반화 / 전문화에서 다이어그램을 작성했듯이.

이 경우를 다루기 위해 mysql 테이블을 디자인하는 데 도움이되는 세 가지 기술이 있습니다. 이를 단일 테이블 상속, 클래스 테이블 상속 및 공유 기본 키라고합니다. 정보 탭에서 해당 태그의 SO를 읽을 수 있습니다.

/programming//tags/single-table-inheritance/info

/programming//tags/class-table-inheritance/info

/programming//tags/shared-primary-key/info

단일 테이블 상속은 NULL이 존재해도 문제가 발생하지 않는 간단한 경우에 유용합니다. 클래스 테이블 상속은 더 복잡한 경우에 더 좋습니다. 공유 기본 키는 일대일 관계를 강화하고 조인 속도를 높이는 좋은 방법입니다.


1

개인 유형 테이블을 작성하고 유형 시행이 필요한 모든 테이블에 필드를 추가 할 수 있습니다. 그런 다음 외래 키를 만듭니다. 다음은 당신에게서 얻은 예입니다 ...

    CREATE TABLE person_type (
        person_type_id int PRIMARY KEY
        -- data: 1=civil, 2=worker
        -- Other fields (such as a label)...
    );

    CREATE TABLE person (
        person_id int PRIMARY KEY
        person_type_id int FOREIGN KEY REFERENCES person_type (person_type_id)
        -- Other fields...
    );

    CREATE TABLE civil (
        civil_id int PRIMARY KEY REFERENCES person (person_id)
        person_type_id int FOREIGN KEY REFERENCES person (person_type_id)
        -- Other fields...
    );

    CREATE TABLE worker (
        worker_id int PRIMARY KEY REFERENCES person (person_id)
        person_type_id int FOREIGN KEY REFERENCES person (person_type_id)
        -- Other fields...
    );

    CREATE TABLE event (
        event_id int PRIMARY KEY,
        person_id int REFERENCES person (person_id)
        -- Type is optional here, but you could enforce event for a particular type
        person_type_id int FOREIGN KEY REFERENCES person (person_type_id)
        -- Other fields...
    );
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.