Mysql

MySQL如何對兩個表的繼承建模

  • August 18, 2020

我有一些儲存數據的表,根據從事工作的人(工人/公民)的類型,我想將其儲存在event表中,現在這些人拯救了一隻動物(有一張animal表)。

最後,我想要一個表來儲存一個人(工人/文職人員)拯救動物的事件,但是我應該如何添加外鍵或如何知道id完成這項工作的文職人員或工人的價值?

現在,在這個設計中,我不知道如何關聯哪個人做了這項工作,如果我只有一種人(又名平民)我只會將civil_id淡水河谷儲存person在最後一張表的列中……但是如何知道是公務員還是工人,我需要其他“中級”表嗎?

如何在 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' );

但是,有沒有辦法擺脫空值?

我的查詢是:

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

既然我製作了圖表,我會更好地回答;)

不幸的是,目前的關係數據庫不直接支持繼承,因此您需要將其轉換為“普通”表。這樣做通常有3種策略:

  1. 單個表中的所有類1具有可以為 NULL 的非公共欄位。
  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既不是civil也不是(即你可以實例化抽像類),並且worker還會讓你創建一個person既是 是。有一些方法可以在數據庫級別強制執行前者,並且在支持延遲約束3的 DBMS 中,即使後者也可以在數據庫中強制執行,但這是使用應用程序級別完整性實際上可能更可取的少數情況之一.civil``worker


1 person,在這種情況下civilworker

2 civilworker在這種情況下(person是“抽象的”)。

3 MySQL 沒有。

不需要區分 Civil_ID 和 Worker_ID;只需繼續使用 Person-ID 作為所有三個表的鍵:Person、Civil 和 Worker。將列 PersonType 添加到具有兩個值“Civil”和“Worker”的 Person。

這現在將抽象基類 PersonClass 的兩個子類 CivilClass 和 WorkerClass 表示為基實體 Person 的子實體 Civil 和 Worker。您可以在 DB 中的數據模型與應用程序中的對像模型之間獲得很好的對應關係。

引用自:https://dba.stackexchange.com/questions/36573