I want to implement class either-or table inheritance (Account, CatAccountDetails, DogAccountDetails) in SQL Server.
I found a recommendation for MySQL:
How do I map an IS-A relationship into a database?
Basically, it is:
- use identical primary keys between the parent table (Account) and the subtype tables (CatAccountDetails, DogAccountDetails)
- add a subtype discriminator column to the parent table and the subtype tables
- include both the shared primary keys and subtype columns in a foreign key constraint from subtype to parent type tables
Adding a type column that is constrained to a single value (e.g. a 'C' column in CatAccountDetails) feels just a little hackish, so I wondered if there is a feature in SQL Server to enable this scenario?
Also, if this is the way to do it, should I define something additionally to prevent this 'unused' column from degrading performance when my ORM (Entity Framework) requests a table join, like create an additional foreign key on just the PK?
The main problem is that CatAccountDetails
will have different columns from DogAccountDetails
. Cats have both different and far more properties than dogs in my application. Side note, 'cats' and 'dogs' represent three categories of website members in my current scenario.
1 Answer 1
Ultimately, I implemented ypercube's suggestion from comments:
The "type" column can be defined as a computed (but constant) column in SQL-Server. I think it has to be
PERSISTED
though so it can participate in the Foreign Key constraint.
This worked well both for performance and compatibility with with my tools (Entity Framework <= 6.0):
CREATE TABLE [dbo].[Account](
[Id] [int] IDENTITY(1000,1) NOT NULL PRIMARY KEY CLUSTERED,
[CommunityRole] [int] NOT NULL,
[FirstName] [nvarchar](50) NOT NULL,
[LastName] [nvarchar](50) NOT NULL,
CONSTRAINT [UX_Derived_Relation] UNIQUE ([Id], [CommunityRole]))
CREATE TABLE [dbo].[Recruiter](
[Id] [int] NOT NULL PRIMARY KEY CLUSTERED,
[CommunityRole] AS ((1)) PERSISTED NOT NULL,
[RecruiterSpecificValue] [int] NOT NULL,
FOREIGN KEY ([Id], [CommunityRole]) REFERENCES Account([Id], [CommunityRole]))
CREATE TABLE [dbo].[Candidate](
[Id] [int] NOT NULL PRIMARY KEY CLUSTERED,
[CommunityRole] AS ((2)) PERSISTED NOT NULL,
[CandidateSpecificValue] [int] NOT NULL,
FOREIGN KEY ([Id], [CommunityRole]) REFERENCES Account([Id], [CommunityRole]))
This mapped well to my implementation of multiple discrete account types, Recruiter and Candidate, on my Job Board.
Explore related questions
See similar questions with these tags.