A
A
Anton Dyshkant2017-05-22 20:00:25
MySQL
Anton Dyshkant, 2017-05-22 20:00:25

What is the best way to implement One-To-One communication in MySQL (Symfony3, Doctrine ORM)?

I had a need to work with a database created 10 years ago. There I found some things that seemed a little strange to me (if I'm wrong, please correct me).
Suppose there is an entity MainEntity, which corresponds in a 1-to-1 scheme to heterogeneous (i.e., different in structure) entities AdditionalEntity1, AdditionalEntity2 and AdditionalEntity3. I expected to see the following database schema:

Expected DB Structure

CREATE TABLE `main_entity` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `additional_entity_1_id` int(11) NOT NULL,
  `additional_entity_2_id` int(11) NOT NULL,
  `additional_entity_3_id` int(11) NOT NULL,
   PRIMARY KEY (`id`)
) ENGINE=InnoDB;

CREATE TABLE `additional_entity_1` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;

CREATE TABLE `additional_entity_2` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;

CREATE TABLE `additional_entity_3` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;

ALTER TABLE `main_entity`
  ADD KEY `additional_entity_1_id` (`additional_entity_1_id`),
  ADD KEY `additional_entity_2_id` (`additional_entity_2_id`),
  ADD KEY `additional_entity_3_id` (`additional_entity_3_id`);

ALTER TABLE `main_entity`
  ADD CONSTRAINT `main_entity_ibfk_1` FOREIGN KEY (`additional_entity_1_id`) REFERENCES `additional_entity_1` (`id`),
  ADD CONSTRAINT `main_entity_ibfk_2` FOREIGN KEY (`additional_entity_2_id`) REFERENCES `additional_entity_2` (`id`),
  ADD CONSTRAINT `main_entity_ibfk_3` FOREIGN KEY (`additional_entity_3_id`) REFERENCES `additional_entity_3` (`id`);


However, I saw this:
Actual DB Structure

CREATE TABLE `main_entity` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
   PRIMARY KEY (`id`)
) ENGINE=InnoDB;

CREATE TABLE `additional_entity_1` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `main_entity_id` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;

CREATE TABLE `additional_entity_2` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `main_entity_id` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;

CREATE TABLE `additional_entity_3` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `main_entity_id` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;

ALTER TABLE `additional_entity_1`
  ADD KEY `main_entity_id` (`main_entity_id`),
  ADD UNIQUE KEY `id__main_entity_id` (`id`, `main_entity_id`);

ALTER TABLE `additional_entity_2`
  ADD KEY `main_entity_id` (`main_entity_id`),
  ADD UNIQUE KEY `id__main_entity_id` (`id`, `main_entity_id`);

ALTER TABLE `additional_entity_3`
  ADD KEY `main_entity_id` (`main_entity_id`),
  ADD UNIQUE KEY `id__main_entity_id` (`id`, `main_entity_id`);

ALTER TABLE `additional_entity_1`
  ADD UNIQUE KEY `main_entity_id` (`main_entity_id`);

ALTER TABLE `additional_entity_1`
  ADD CONSTRAINT `additional_entity_1_ibfk_1` FOREIGN KEY (`main_entity_id`) REFERENCES `main_entity` (`id`);

ALTER TABLE `additional_entity_2`
  ADD CONSTRAINT `additional_entity_2_ibfk_1` FOREIGN KEY (`main_entity_id`) REFERENCES `main_entity` (`id`);

ALTER TABLE `additional_entity_3`
  ADD CONSTRAINT `additional_entity_3_ibfk_1` FOREIGN KEY (`main_entity_id`) REFERENCES `main_entity` (`id`);


In fact, at the code level, the same thing turns out: a one-to-one relationship connects each of the auxiliary entities with the main one.
However, it is impossible not to notice that at the database level these are two fundamentally different schemes.
My questions :
  1. How are these schemes different? Are there any "pitfalls" of each of these implementations?
  2. Which scheme is more preferable to use (including taking into account the use of Doctrine and Symfony3)?

Answer the question

In order to leave comments, you need to log in

3 answer(s)
V
Vladislav Vlastovskiy, 2017-05-23
@VlastV

You can use any scheme.
I would choose the second one, since when adding / deleting new types of relations, it is not necessary to make ALTER TABLE the main one.
In Doctrine, these relationships are implemented in the same way, through One-To-One, with the only difference being which entity will have a relationship.
In general, the database structure should be logical, for example, should MainEntity know about AdditionalEntity1, or should AdditionalEntity1 know about MainEntity.

X
xmoonlight, 2017-05-23
@xmoonlight

You gave 2 special cases, but did not give a description of the interaction of these entities.
Therefore, it is impossible to give an unequivocal answer at the moment: there is little data.
1. You don't always need a hard link by key in the database
2. You don't always need a cross-link (I know everything about each other)
It all depends on the business process and the task of selecting data in this process.

I
Ildar, 2017-06-19
@vistoyn

1. There are errors in the first option:
- If you get a record from the additional_entity_N table, it will not be clear which main_entity this record belongs to, in order to find out, you need to make an additional request to the main_entity.
- Additional_entity_N tables may have entries that do not belong to any entry from main_entity.
- It is easy to get confused when debugging the database, because the id in all 4 tables is different.
- To add a new additional_entity_N you will need to create an additional_entity_N entry and then change the values ​​in main_entity.
- And what will you do if you have created an entry in the additional_entity_1 table, and the main_entity already has an additional_entity_1_id id?
2. In the second option, you have errors:
- You have a 1-to-many relationship, not one to one.
- Additional_entity_N tables do not need auto-increment, the id field must be removed.
- Primary key in additional_entity_N tables must be main_entity_id.
- All 4 tables must have the same ID Primary key.
3. If you correct errors in the second option, then it is more correct to use it.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question