What is the best way to implement Polymorphic Association in SQL Server?
I have tons of instances where I need to implement some sort of Polymorphic Association in my database. I always waste tons of time thinking through all the options all over again. Here are the 3 I can think of. I'm hoping there is a best practice for SQL Server.
Here is the multiple column approach
Here is the no foreign key approach
And here is the base table approach
Another common Name for this model is the Supertype Model, where one has a base set of attributes that can be expanded via joining to another entity. In Oracle books, it is taught both as a logical model and physical implementation. The model without the relations would allow data to grow into invalid state and orphan records I would strongly validate the needs before selecting that model. The top model with the relation stored in the base object would cause nulls, and in a case where fields were mutually exclusive you would always have a null. The bottom diagram where the key is enforced in the child object would eliminate the nulls but also make the dependency a soft depenendency and allow orphans if cascading was not enforced. I think assessing those traits will help you select the model that fits best. I have used all three in the past.
I used the following solution to solve a similar problem :
Many-Many based design : Even though the relation is a 1-Many between an ObjectN and Something, it is equivalent to a Many-Many relationship with a modification of the PK of the relation table.
First i create a relation table between an ObjectN and Something per Object and then i use the Something_ID column as the PK.
This is the DDL of the Something-Object1 relationship which is the same for Object2 and Object3 as well :
CREATE TABLE Something
(
ID INT PRIMARY KEY,
.....
)
CREATE TABLE Object1
(
ID INT PRIMARY KEY,
.....
)
CREATE TABLE Something_Object1
(
Something_ID INT PRIMARY KEY,
Object1_ID INT NOT NULL,
......
FOREIGN KEY (Something_ID) REFERENCES Something(ID),
FOREIGN KEY (Object1_ID) REFERENCES Object1(ID)
)
More details and examples of other possible options in this ticket multiple-foreign-keys-for-the-same-business-rule
The two most common approaches are Table Per Class (i.e. a table for the base class and another table for each subclass that contains the additional columns necessary to describe the subclass) and Table Per Hierarchy (i.e. all columns in one table, with one ore more columns to allow for the discrimination of subclasses). Which is the better approach really depends on the particulars of your application and data access strategy.
You would have Table Per Class in your first example by reversing the direction of the FK and removing the extra ids from the parent. The other two are essentially variants of table per class.