J'ai des tables où je stocke des données et selon le type de personne (travailleur, civil) qui a fait un travail, je veux le stocker dans une table event
, maintenant ces gars sauvent un animal (il y a un animal
table).
Enfin, je veux avoir une table pour stocker l'événement qu'un gars (travailleur, civil), a sauvé un animal, mais archet dois-je ajouter une clé étrangère ou comment connaître la valeur id
du civil ou du travailleur qui a fait le boulot?
Maintenant, dans cette conception, je ne sais pas comment identifier la personne qui a fait le travail si, je n'avais qu'une sorte de personne (alias civile), je ne stockerais que le civil_id
vale dans une colonne person
dans ce dernier tableau ... mais comment savoir s'il était civil ou ouvrier, ai-je besoin d'un autre tableau "intermédiaire"?
Comment refléter la conception du diagramme suivant dans MySQL?
Je l'ai modélisé de la manière suivante:
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' );
Cependant, existe-t-il un moyen de se débarrasser des null?
Les requêtes que j'ai sont:
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 ;
Voici une mise à jour sqlfiddle.
Depuis que j'ai fait le schéma, je ferais mieux de répondre;)
Les bases de données relationnelles actuelles ne prennent malheureusement pas directement en charge l'héritage, vous devez donc le transformer en tables "simples". Il existe généralement 3 stratégies pour le faire:
Pour en savoir plus sur ce que cela signifie réellement et certains avantages et inconvénients, veuillez consulter les liens fournis dans mon article d'origine , mais en un mot, le (3) devrait probablement être votre valeur par défaut, sauf si vous avez une raison spécifique pour l'un des deux autres. Vous pouvez représenter le (3) dans la base de données simplement comme ceci:
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...
);
Malheureusement, cette structure vous permettra d'avoir un person
qui n'est ni civil
ni worker
(c'est-à-dire que vous pouvez instancier la classe abstraite), et vous permettra également de créer un person
c'est-à-dire à la fois civil
et worker
. Il existe des moyens pour appliquer le premier au niveau de la base de données et dans un SGBD qui prend en charge les contraintes différées3 même ce dernier peut être appliqué dans la base de données, mais c'est l'un des rares cas où l'utilisation de l'intégrité au niveau de l'application pourrait être préférable.
1 person
, civil
et worker
dans ce cas.
2 civil
et worker
dans ce cas (person
est "abstrait").
3 Ce que MySQL ne fait pas.
Il n'y a pas besoin de Civil_ID et Worker_ID distincts; continuez simplement à utiliser Person-ID comme clé pour les trois tables: Person, Civil et Worker. Ajoutez une colonne PersonType à Person avec les deux valeurs "Civil" et "Worker".
Cela représente désormais les deux sous-classes CivilClass et WorkerClass de la classe de base abstraite PersonClass en tant que sous-entités Civil et Worker de l'entité de base Person. Vous obtenez une belle correspondance entre le modèle de données dans la base de données avec le modèle d'objet dans l'application.
Votre cas est une instance de modélisation de classe/sous-classe. Ou, comme vous l'avez schématisé dans ER, généralisation/spécialisation.
Il existe trois techniques qui vous aideront à concevoir des tables mysql pour couvrir ce cas. Ils sont appelés héritage de table unique, héritage de table de classe et clé primaire partagée. Vous pouvez les lire dans l'onglet info de la balise correspondante dans 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
L'héritage de table unique est utile dans les cas simples où la présence de valeurs NULL ne pose pas de problème. L'héritage de table de classe est préférable pour les cas plus compliqués. La clé primaire partagée est un bon moyen d'imposer des relations un à un et d'accélérer les jointures.
Vous pouvez créer une table de type de personne et ajouter un champ à toutes les tables nécessitant l'application du type. Créez ensuite des clés étrangères. Voici un exemple dérivant du vôtre ...
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...
);