什么时候SQL Server外键表太多了?

时间:2012-12-08 21:45:58

标签: sql sql-server-2008 database-design

当我有以下两个表时,StatusTypes表是否会被视为过度杀伤?即使用它比获得更多好处吗?

在这种情况下,我不希望在管理员后端加载这些状态以添加或更改/删除它们,但另一方面我不喜欢不使用外键。

我正在寻找支持和反对分离状态类型或将其保留在Audit表中的原因。

任何帮助都将不胜感激。

 -- 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

2 个答案:

答案 0 :(得分:1)

在这种情况下,我喜欢保留查找表以强制状态为一组类型之一。有些数据库有枚举类型,或者可以使用检查约束,但这是最便携的方法IMO。

但是,我使查找表只包含一个包含类型名称的字符串列。这样你就不必真正加入查找表,而你的ORM(假设你使用的是ORM)可能完全没有意识到它。

在这种情况下,架构看起来像:

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

对特定类型的审计项目的查询将是:

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

因此仍然强制执行参照完整性,但查询不需要额外的连接。

答案 1 :(得分:0)

我会提出一个反驳论点:在最有用的地方使用你的开发时间。也许你不需要这个运行时检查那么多。也许您可以将开发时间用于其他更有用的检查。

是否可能会设置无效的状态值?你的应用程序肯定会使用一组常量或枚举,因此不太可能出现一些流氓值。

尽管如此,确保诚信有很多价值。我喜欢使用BETWEEN检查约束来覆盖我的所有“枚举”列,这可以在运行时快速完成甚至更快。