Hybrid Database Relationships? - mysql

What is a relationship called when there are three entities, Table1 Table2 and Table3
Table1 has a One To One Relationship with Table3
Table2 has a One To Many Relationship with Table3
Table3 has two composite keys, Table1ID and Table2ID.
What is this relationship called? I'm trying to figure out how to model this in an ORM but because I don't even know what the relationship is, I don't even know where to begin.

We'd normally refer to that as reflexive or bi-directional.
Handling this in an ORM is non-trivial.
If you could remove the Table1ID column from Table3 (removing the foreign key pointing back), that would simplify the model. But that may not be an option for you.
Hibernate would refer to this as a bi-directional association; Hibernate only persists one "end" of that association; it won't maintain foreign keys in both directions.
EDIT
I reviewed the model diagram (from the link you provided in a comment).
It looks very much like the personVehicle table is an association table, between person and vehicle. This is the same pattern we would see in resolving a many-to-many relationship. Your model looks like a special case of a many-to-many, where one side of the relationship is constrained to just one.
In terms of keys, your model looks like this:
person
id PK
vehicle
id PK
personVehicle
person_id PK, FK->person(id)
vehicle_id PK, FK->vehicle(id)
If I understood what you are asking, you are wanting to represent a foreign key constraint on the vehicle table that points back to a row in the personVehicle table:
vehicle
id PK, FK->personVehicle(vehicle_id)
I don't know of any ORM that is going to maintain that type of bi-directional foreign key in the vehicle table for you automatically. (I don't think it's impossible to maintain the value in a foreign key column, it's not just possible to "declare" this association in a way where an ORM will maintain the foreign keys in both directions.
(Some databases, such as Oracle, allow us to create and maintain relationships like this, by allowing foreign constraints to be DEFERRED while we are inserting, updating and deleting, and postponing the checks on foreign key constraints until COMMIT.)
If there was a foreign key, from vehicle, pointing to a row in personVehicle, and there's a requirement that the row in personVehicle is required to refer back to the EXACT same row in the vehicle table (and not just some row) then you don't really need a foreign key in the vehicle table. The relationship is already represented sufficiently in the model by the foreign key in the personVehicle table.
If you need to enforce a constraint that a vehicle can be related to at most one personVehicle, that calls for a UNIQUE constraint on personVehicle(vehicle_id). That represents the requirement sufficiently in the model.
If this is truly one-to-one, and you need a foreign key, then this would actually be equivalent to removing the vehicle table entirely, and merging the attributes from that table into the personVehicle table.
EDIT
My use of the term reflexive may be incorrect. I usually refer to a table that has a foreign key reference to a column in the same table as being recursive.
In terms of a relationship between two tables, where each table has foreign key that refers to the other table... in the case where row in t1 refers to a row in t2, and that row in t2 refers back to t1, not to just any row, but back to the EXACT same row that referred to it... I think of that in terms of the relationship being "reflected" back.
The relationship reflects back. But we don't use the term "reflection" since that term has a special meaning in Java. So, maybe the only term that is appropriate is "bi-directional".
The typical bi-directional one-to-one relationship is the row in one table points to a row in the other table, which points back to the EXACT same row in the original table:
For example:
t1 t2
id t2_id id t1_id
--- ----- ---- ------
1 A A 1
2 B B 2
3 C C 3
Another form would be where a row did not necessarily refer back to the same row that referenced it. (This is not usually limited to a one-to-one), but we still have foreign keys that point in both directions (from t1 to t2, and from t2 to t1)
For example:
t1 t2
id t2_id id t1_id
--- ----- --- ----
1 A A 2
2 B B 3
3 C C 1
In the first case, we have a requirement where a row has a foreign key value that refers ONLY to a row in the other table that refers back to original row. The relationship "reflects" back.
In the second case, we don't have that requirement. If I start with row 1, it points to row A, which points back to row 2.
In terms of defining the foreign key relationships in the database, thee definition of the constraint is the same. The difference is usually whether the foreign key columns can be NULL, or have to be UNIQUE.
I thought there was a term other than just "bi-directional" that distinguished the first case from the more general second case. I thought I had used the term "reflexive" or "reflective", but I may be mistaken.
In terms of a "recursive" relationship, where a foreign key points back to a row in the same table, that foreign key (almost) always refers to a DIFFERENT row in the table; it does not refer back to itself.

Related

How to model diamond like many-to-many relationship in database ERD

Legend:
PK (Blue): Primary key
FK (Green): Foreign key
PFK (Blue): Primary Key and Foreign Key at the same time
How to model a diamond like (if term is correct) relationship? Better to explain using a simplified example:
There is organization, item and tag entities.
My aim is to model:
Every tag is unique by itself and belongs to a single organization.
Every item is unique by itself and belongs to a single organization.
Items have many tags (joined using M2M table) and related tag/item pairs must belong to same organization. (i.e. item from organization A cannot pair with a tag from organization B)
I diagrammed two alternative solutions, but none of them satisfied me.
Diagram 1 breaks 3rd aim: items and tags are unique by themselves using id as primary key, but there is nothing to stop insert pairs into item_tag which belong to different organization.
Diagram 2 does not break, but bends 1st and 2nd aims: organization_id is added as a Primary and Foreign Key to item and tag tables and item_tag.organization_id column references both. This prevents pairs from different organization. tag.id and item.id columns are part of a unnecessary composite primary key now, because in reality single id column represents uniqueness of the item and tag.
How can I model those requirements correctly?
To enforce referential integrity, you'll have to ...
include organization_id in all tables
create logically redundant UNIQUE (or PK) constraints on (organization_id, id) in both tables tag and item
have multicolumn FK constraints in item_tag matching the columns of those UNIQUE constraints.
If you don't include the organization_id (logically redundantly) there would be nothing to keep you from linking items and tags from different organizations (by mistake).
That would be your diagram 2. But do you really need data type uuid for tags? bigint or even int should suffice, while being a bit smaller and faster.
Closely related case with code example for PostgreSQL:
Enforcing constraints “two tables away”

Unable to figure how to manage foreign keys for 'project-customers-contacts' relation

I have a CUSTOMERS table and a CONTACTS table the relation between them is one to many obviously.
also I have PROJECTS table and PROJECT_CUSTOMERS table with relation one to many and with relation one to one between CUSTOMERS and PROJECT_CUSTOMERS.
my problem is that I have a fifth table PROJECT_CONTACTS ....I can't figure which tables shall I refer to in this tables, currently I am refering to PROJECT_CUSTOMERS and CONTACTS table, is this correct or there is something better ?
Your title refers to "foreign keys" but your question just seems to be about what columns should go in what tables.
First, decide what situations can arise and what you want/need to say about them. (This will your tables, columns, candidate keys, foreign keys and constraints.)
Every table holds rows that make some predicate (statement template parameterized by column names) true. Your design seems to have:
CUSTOMERS(id, ...) -- ID identifies a customer and ...
CONTACTS(id, ...) -- ID identifies a contact and ...
PROJECTS(id, ...) -- ID identifies a project and ...
PROJECT_CUSTOMERS(pid, cust_id, ...) -- project PID has customer CUST_ID and ...
PROJECT_CONTACTS(pid, cont_id, cust_id)...)
-- project PID has contact CONT_ID and project pid has customer CUST_ID and ...
A foreign key has a table & column list referencing a table and column list that forms a candidate key. It says that lists of values in the first table appear as lists of values in the second table. Where that is so, declare a foreign key.

Mysql composite primary key

I want to have a lookup table that links two of the same things to eachother. Say I have a 'Person' table and I want to lookup the relationship between two people. I'll have column one of the lookup be 'PersonId1' and column two be 'PersonId2' and the third column be 'Relationship'. Since the relationship goes both ways I don't need to have duplicate records with the PlayerId's switched. Is there any way to make mysql enforce uniqueness on PlayerId1 and PlayerId2 combinations regardless of which order they're in?
Does that make sense?
Short answer: No.
Longer answer: You could set up a trigger to swap the order of the two person ids if the second were smaller than the first, then write them, and use a composite key.
Even longer answer: Not all interpersonal relationships are commutative (not all relationships go both ways). What about the "Employee" or "Mother" relationships? Even the "Friend" relationship, which is presumably peer-to-peer, might be better represented if you had separate rows saying A is B's Friend and B is A's Friend. So maybe you want a three-field composite key on this table.
You mean you want to have a unique row record from PersonID1 and PersonID2 Column (regardless of the Relationship column)? If that so, you may use the Composite key (Multi column key).
Here's an example:
CREATE TABLE Person (
PersonId1 INT,
PersonId2 INT,
PRIMARY KEY (PersonId1, PersonId2)
)
+1 for composite pk. To prevent duplicate combinations, an extra varchar column with for example personid1+personid2 with a unique constraint on it may be a solution...
See also: person data model example

MySQL Database design. Inserting rows in 1to1 tables.

What is the best way to insert rows into tables with references 1 to 1 of each other?
I mean, in a MySQL 5.5 and tables InnoDB, I have a database design similar to the following
The problem arises when we try to insert rows in table1 and table2. Since there is no multi-table insert in MySQL, I can not insert a row becouse the foreign keys are NOT NULL fields in both tables and should be inserted simultaneously in both.
Which is the bes way to solve this problem?
I have in mind 3 possible solutions, but I want to know if there are more than these or which is the best and why.
Set the foreign key field as NULLABLE and after insert one row in a table, insert the other one and afterwards, update de first one.
Just as indicated above but with an special value like -1. First, insert in one table with foreign key = -1 that is equivalent to NULL but avoiding set the field as NULLABLE. Afterwards, we insert the row in the other table and update the first one inserted.
Create a relational table between both though it is not really necessary because it is a 1 to 1 ratio
Thanks!!
EDIT
I briefly explain what I need this circular relationship: It is a denormalization from the parent table to one of its childs. It is made in order of high performance to have always the reference of the best ranked child from a parent table.
I'll make this an answer as I feel this is a design flaw.
First, if the two tables are in true 1:1 relationship, why don't you just have one table?
Second, if it's not a true 1:1 relationship but a supertype-subtype problem, you don't need this circular foreign keys either. Lets say table1 is Employee and table2 is Customer. Off course most customers are not employees (and vice-versa). But sometimes a customer may be an employee too. This can be solved having 3 tables:
Person
------
id
PRIMARY KEY: id
Employee
--------
personid
lastname
firstname
... other data
PRIMARY KEY: personid
FOREIGN KEY: personid
REFERENCES Person(id)
Customer
--------
personid
creditCardNumber
... other data
PRIMARY KEY: personid
FOREIGN KEY: personid
REFERENCES Person(id)
In the scenario you describe you have two tables Parent and Child having 1:N relationship. Then, you want to store somehow the best performing (based on a defined calculation) child for every parent.
Would this work?:
Parent
------
id
PRIMARY KEY: id
Child
-----
id
parentid
... other data
PRIMARY KEY: id
FOREIGN KEY: parentid
REFERENCES Parent(id)
UNIQUE KEY: (id, parentid) --- needed for the FK below
BestChild
---------
parentid
childid
... other data
PRIMARY KEY: parentid
FOREIGN KEY: (childid, parentid)
REFERENCES Child(id, parentid)
This way, you enforce the wanted referential integrity (every BestChild is a Child, every Parent has only one BestChild) and there is no circular path in the References. The reference to the best child is stored in the extra table and not in the Parent table.
You can find BestChild for every Parent by joining:
Parent
JOIN BestChild
ON Parent.id = BestChild.parentid
JOIN Child
ON BestChild.childid = Child.id
Additionally, if you want to store best children for multiple performance tests (for different types of tests, or tests in various dates), you can add a test field, and alter the Primary Key to (test, parentid):
BestChild
---------
testid
parentid
childid
... other data
PRIMARY KEY: (testid, parentid)
FOREIGN KEY: (childid, parentid)
REFERENCES Child(id, parentid)
FOREIGN KEY: testid
REFERENCES Test(id)
I'd create a blackhole table and put a trigger on that to take care of inserts
CREATE TABLE bh_table12 (
table1col varchar(45) not null,
table2col varchar(45) not null
) ENGINE = BLACKHOLE
and put a trigger on that to take care of inserts
DELIMITER $$
CREATE TRIGGER ai_bh_table12_each AFTER INSERT ON bh_table12 FOR EACH ROW
BEGIN
DECLARE mytable1id integer;
DECLARE mytable2id integer;
SET foreign_key_checks = 0;
INSERT INTO table1 (table1col, table2_id) VALUES (new.table1col, 0);
SELECT last_insert_id() INTO mytable1id;
INSERT INTO table2 (table2col, table1_id) VALUES (new.table2col, table1id);
SELECT last_insert_id() INTO mytable2id;
UPDATE table1 SET table2_id = mytable2id WHERE table1.id = mytable1id;
SET foreign_key_checks = 1;
END $$
DELIMITER ;
Note that actions in a trigger are part of one transaction (when using InnoDB or likewise), so an error in the trigger will rollback partial changes.
Note on your table structure
Note that if it's a 1-on-1 table, you only need to put a table2_id in table1 and no table1_id in table2 (or visa versa).
If you need to query table1 based on table2 you can just use:
SELECT table1.* FROM table1
INNER JOIN table2 on (table2.id = table1.table2_id)
WHERE table2.table2col = 'test2'
Likewise for the other way round
SELECT table2.* FROM table2
INNER JOIN table1 on (table2.id = table1.table2_id)
WHERE table1.table1col = 'test1'
Links:
http://dev.mysql.com/doc/refman/5.1/en/blackhole-storage-engine.html
http://dev.mysql.com/doc/refman/5.1/en/triggers.html
I feel this is an important question, and I haven't found any 100% satisfying answer throughout the web. The 2 answers that you have given are the best ones I found, yet they are not 100% satisfactory.
Here's why :
The reason why Emilio cannot put his best child inside his parent table is pretty simple, I presume, because I share the same problem : not every child will be labelled as a parent's best child. So he would still need to store information on other children somewhere else. In that case, he would have some information about the best children in their parent's table, and other children in a separate database. This is a huge mess. For example, the day he wants to change the data structure about children, he needs to change it in both tables. Every time he writes a query on all children, he should query both tables, etc...
the reason why Emilio cannot just set the best child foreign key to nullable (I presume for Emilio, but for me it would be very strict), is that he needs to be sure that a parent always has a best child. In Emilio's case it's maybe not very easy to imagine, but in mine, I cannot have the equivalent of the parent have no child.
Thus I would have tended to think that the solution with setting foreign_key_checks to zero would be best, but here is the problem :
after setting foreign_key_checks back to 1, there is no check on data's consistency. Thus, you have a risk of making mistakes in the meantime. You can consider that you won't, but still it is not a very clean solution.

many to many relationship

If I have two tables - table beer and table distributor, each one have a primary key and a third table that have the foreign keys and calls beer_distributor
Is it adequate a new field (primary key) in this table? The other way is with joins, correct? To obtain for example DUVEL De vroliijke drinker?
You've definitely got the right idea. Your beer_distributor table is what's known as a junction table. JOINs and keys/indexes are used together. The database system uses keys to make JOINs work quickly and efficiently. You use this junction table by JOINing both beer and distributor tables to it.
And, your junction table should have a primary key that spans both columns (a multiple-column index / "composite index"), which it looks like it does if I understand that diagram correctly. In that case, it looks good to me. Nicely done.
I would put a primary key in the join table beer_distributor, not a dual primary key of the two foreign keys. IMO, it makes life easier when maintaining the relationship.
UPDATE
To emphasize this point, consider having to change the distributor ACOO9 for beer 163. With the dual primary key, you'd have to remove then reinsert OR know both existing values to update the record. With a separate primary key, you'd simply update the record using this value. Comes in handy when building applications on top this data. If this is strictly a data warehouse, then a dual primary key might make more sense from the DBA perspective.
UPDATE beer_distributor SET distributor_id = XXXXX WHERE beer_id = 163 AND distributor_id = AC009
versus
UPDATE beer_distributor SET distributor_id = XXXXX WHERE id = 1234