web-dev-qa-db-ja.com

2つのテーブルMySQLの継承をモデル化する方法

データを保存するテーブルがいくつかあり、eventテーブルに保存したい仕事をした人のタイプ(労働者、市民)に応じて、これらの人が動物を救出します(animalテーブルがあります)。

最後に、男(労働者、市民)が動物を救ったというイベントを格納するテーブルが欲しいのですが、外部キーを追加する必要があるのでしょうか、それとも、仕事をした市民または労働者のid値を知る方法はありますか?

さて、この設計では、どの人が仕事をしたかを関連付ける方法がわかりません、私は一種の人(別名市民)しかいなかったので、この最後のテーブルのperson列にcivil_id値のみを保存します...しかし、それが民事か労働者かを知る方法、私は他の「中間」テーブルが必要ですか?

次の図の設計をMySQLに反映するにはどうすればよいですか?

enter image description here

追加の詳細

私はそれを次のようにモデル化しました:

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' );

しかし、ヌルを取り除く方法はありますか?

私が持っているクエリは:

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です。

16
cMinor

ダイアグラムを作成したので、私はよりよく答えます;)

残念ながら現在のリレーショナルデータベースは継承を直接サポートしていないため、「プレーン」テーブルに変換する必要があります。これを行うには、一般に3つの方法があります。

  1. 全クラス1 NULL可能な非共通フィールドを持つ単一のテーブル内。
  2. 具体的なクラス2 別のテーブル。抽象クラスには、独自のテーブルはありません。
  3. 別々のテーブルのすべてのクラス。

これが実際に何を意味するか、そしていくつかの長所と短所については、私の 元の投稿 で提供されているリンクを参照してください。ただし、具体的な理由がない限り、簡単に言えば(3)がデフォルトになります他の2つのうちの1つ。次のように、データベースで(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でもcivilでもないworkerを使用でき(つまり、抽象クラスをインスタンス化できます)、personを作成できますbothcivilおよびworker方法があります 前者をデータベースレベルで適用し、DBMSで遅延制約をサポートする 後者でもデータベース内で実施できますが、これはアプリケーションレベルの整合性を使用することが実際に望ましい数少ないケースの1つです。


1 この場合、personcivilworker

2 この場合、civilおよびworkerpersonは "abstract")です。

 どのMySQLはそうしません。

15

個別のCivil_IDとWorker_IDは必要ありません。 Person-IDを、Person、Civil、Workerの3つのテーブルすべてのキーとして引き続き使用します。 「Civil」と「Worker」の2つの値を持つ列PersonTypeをPersonに追加します。

これは、基本エンティティPersonのサブエンティティCivilおよびWorkerとして、抽象基本クラスPersonClassの2つのサブクラスCivilClassおよびWorkerClassを表します。 DBのデータモデルとアプリケーションのオブジェクトモデルがうまく対応します。

5
Pieter Geerkens

あなたのケースは、クラス/サブクラスモデリングのインスタンスです。または、ERで図化したように、汎化/特殊化。

このケースをカバーするmysqlテーブルの設計に役立つ3つのテクニックがあります。これらは、単一テーブル継承、クラステーブル継承、および共有主キーと呼ばれます。あなたはSOの対応するタグから情報タブでそれらを読むことができます。

https://stackoverflow.com/tags/single-table-inheritance/info

https://stackoverflow.com/tags/class-table-inheritance/info

https://stackoverflow.com/tags/shared-primary-key/info

単一テーブルの継承は、NULLの存在が問題を引き起こさない単純な場合に役立ちます。クラステーブルの継承は、より複雑な場合に適しています。共有主キーは、1対1の関係を強制し、結合を高速化するための良い方法です。

4
Walter Mitty

個人タイプテーブルを作成し、タイプの適用が必要なすべてのテーブルにフィールドを追加できます。次に、外部キーを作成します。これはあなたのものから派生した例です...

    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...
    );
1
Isometriq