When is a SQL Server foreign key table too?

advertisements

When I have the below two tables, would the StatusTypes table be considered as overkill? i.e. is there more benefit to using it than not?

In this situation I don't expect to have to load these statuses up in an admin backend in order to add or change/ delete them, but on the other hand I don't often like not using foreign keys.

I'm looking for reasons for and against separating out the status type or keeping it in the Audit table.

Any help would be appreciated.

 -- i.e. NEW, SUBMITTED, UPDATED
    CREATE TABLE [dbo].[StatusTypes](
        [ID] [int] IDENTITY(1,1) NOT NULL,
        [Name] [nvarchar](250) NOT NULL,
        CONSTRAINT [PK_StatusTypes] PRIMARY KEY CLUSTERED ([ID] ASC)
    ) ON [PRIMARY]
    GO

    CREATE TABLE [dbo].[Audits](
        [ID] [int] IDENTITY(1,1) NOT NULL,
        [Description] [nvarchar](500) NULL,
        [Country_Fkey] [int] NOT NULL,
        [User_Fkey] [int] NOT NULL,
        [CreatedDate] [date] NOT NULL,
        [LastAmendedDate] [date] NULL,
        [Status_Fkey] [int] NOT NULL,
        CONSTRAINT [PK_Audits] PRIMARY KEY CLUSTERED ([ID] ASC)
    ) ON [PRIMARY]
    GO


In this situation I like to keep the lookup table to enforce the status being one of a set of types. Some databases have an enum type, or can use check constraints, but this is the most portable method IMO.

However, I make the lookup table containing only a single string column containing the type's name. That way you don't have to actually join to the lookup table and your ORM (assuming you use one) can be completely unaware of it.

In this case the schema would look like:

CREATE TABLE [dbo].[StatusTypes](
    [ID] [nvarchar](250) NOT NULL,
    CONSTRAINT [PK_StatusTypes] PRIMARY KEY CLUSTERED ([ID] ASC)
) ON [PRIMARY]
GO

CREATE TABLE [dbo].[Audits](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    ...
    [Status] [nvarchar](250) NOT NULL,
    CONSTRAINT [PK_Audits] PRIMARY KEY CLUSTERED ([ID] ASC),
    CONSTRAINT [FK_Audit_Status] FOREIGN KEY (Status) REFERENCES StatusTypes(ID)
) ON [PRIMARY]
GO

And a query for audit items of a particular type would be:

SELECT ...
FROM Audits
WHERE Status = 'ACTIVE'

So referential integrity is still enforced but queries don't need an extra join.