edg*_*tze 20 mysql database-design subtypes
我有一些表格来存储数据,并且根据从事工作的人(工人/文职人员)的类型,我想将其存储在event
表格中,现在这些人拯救了一只动物(有一张animal
桌子)。
最后,我想要一个表来存储一个人(工人/平民)拯救动物的事件,但是我应该如何添加外键或如何知道id
完成这项工作的平民或工人的价值?
现在,在这个设计中,我不知道如何关联哪个人完成了这项工作,如果我只有一种人(又名平民)我只会将civil_id
vale存储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' );
Run Code Online (Sandbox Code Playgroud)
但是,有没有办法摆脱空值?
我的疑问是:
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 ;
Run Code Online (Sandbox Code Playgroud)
这是更新的sqlfiddle。
Bra*_*vic 18
既然我做了图表,我最好回答;)
不幸的是,当前的关系数据库不直接支持继承,因此您需要将其转换为“普通”表。这样做通常有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...
);
Run Code Online (Sandbox Code Playgroud)
不幸的是,这种结构可以让你有一个person
既不是civil
也worker
(即你可以实例化抽象类),并且还将让你创建一个person
是两个 civil
和worker
。有一些方法可以在数据库级别强制执行前者,在支持延迟约束3的 DBMS 中,甚至可以在数据库中强制执行后者,但这是使用应用程序级别完整性实际上可能更可取的少数情况之一.
1 person
,civil
并且worker
在这种情况下。
2 civil
,worker
在这种情况下(person
是“抽象的”)。
3 MySQL 没有。
Pie*_*ens 10
不需要不同的 Civil_ID 和 Worker_ID;只需继续使用 Person-ID 作为所有三个表的键:Person、Civil 和 Worker。将列 PersonType 添加到具有两个值“Civil”和“Worker”的 Person。
这现在将抽象基类 PersonClass 的两个子类 CivilClass 和 WorkerClass 表示为基实体 Person 的子实体 Civil 和 Worker。您可以在 DB 中的数据模型与应用程序中的对象模型之间获得很好的对应关系。
您的案例是类/子类建模的一个实例。或者,正如您在 ER 中绘制的那样,泛化/专业化。
有三种技术可以帮助您设计 mysql 表来涵盖这种情况。它们被称为单表继承、类表继承和共享主键。您可以在 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 不会导致问题的简单情况很有用。类表继承更适合更复杂的情况。共享主键是强制执行一对一关系和加速连接的好方法。
归档时间: |
|
查看次数: |
67830 次 |
最近记录: |