I'am new at DB design and sorry for this noob question.I have 2 simple tables and they have 1 to 1 relation between each other. Which table's PK should be FK in other table ? How can i decide that ?
-
Is the relationship a true `1 :: 1`? (i.e. every row in table A will have a related row in table B - **and vice versa**?) Or a `1::0..1` relationship? (i.e. every row in B will have a related row in A but the rows in A may not (all) have a row in B) – ypercubeᵀᴹ Dec 01 '13 at 19:40
-
@ypercube It is a true one to one relationship. – Tartar Dec 01 '13 at 19:44
2 Answers
In order to decide this, the question to ask is whether the relationship is a true 1 :: 1
or not.
If the relationship is a 1 :: 0..1
(i.e. every row in B will have a related row in A but the rows in A may not (all) have a row in B), then there should be a FOREIGN KEY
in table B (pk)
that REFERENCES A (pk)
. This is the most common situation and it is easy to be implemented in almost all DBMS.
If the relationship is a true 1 :: 1
(i.e. every row in table A will have a related row in table B - and vice versa), then there should be two foreign keys, one from B towards A and another from A towards B. This is also easy to declare but not so trivial to actually make it work.
The problem arises due to the chicken-and-egg problem: Which table should I first insert a row into? If we insert into A first, the foreign key (towards B) will forbid the insert. If we insert into B first, the foreign key (towards A) will forbid the insert this time.
In order to make this work, the 2 insert statements have to be in one transaction - and the foreign keys have to have been defined as DEFERRABLE
- i.e. checked at the end of the transaction. So, if you work in SQL-Server (or MySQL) you simply can't do this. If you are in Postgres or Oracle or any other DBMS that has implemented deferrable constraints, this is achievable.

- 113,259
- 19
- 174
- 235
Which table's PK should be FK in other table?
Both. For a true "1 to 1" you'll need circular foreign keys (which also implies you'll need deferred foreign keys to break "chicken-and-egg" problem when inserting new data, which not all DBMSes support).
Or just merge both tables into one table (which is recommended in most cases).
However, I suspect you are not talking about true "1 to 1", but "1 to 0 or 1", in which case the "0 or 1" endpoint should contain the foreign key, for example:
CREATE TABLE ONE (
ID INT PRIMARY KEY
);
CREATE TABLE ZERO_OR_ONE (
ID INT PRIMARY KEY REFERENCES ONE (ID)
);

- 50,809
- 10
- 93
- 167
-
-
1@Tartar Then just merge them into one table, unless you have [specific reasons](http://stackoverflow.com/a/9688442/533120) not to. – Branko Dimitrijevic Dec 01 '13 at 20:09