【问题标题】:When is a SQL Server foreign key table too much?SQL Server 外键表何时过多?
【发布时间】:2012-12-08 21:45:57
【问题描述】:

当我有以下两个表时,StatusTypes 表会被认为是矫枉过正吗?即使用它比不使用它有更多好处吗?

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

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

任何帮助将不胜感激。

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

【问题讨论】:

  • 在数据库中强制执行参照完整性对于数据库正常工作并为其用户提供价值绝对至关重要。因此,我永远不会说强制执行外键(及其可能值)的查找表太多 - 数据库中不能有太多安全预防措施 - 只有太少....
  • 这几乎是我的想法,但我想就这种情况获得一些其他意见,因为它可能会发生任何一种情况。谢谢

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


【解决方案1】:

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

但是,我使查找表只包含一个包含类型名称的字符串列。这样您就不必实际加入查找表,并且您的 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'

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

【讨论】:

  • 所以你是说你会保留StatusTypes 表,并将文本而不是Audits 表中的StatusType 的外键存储?
  • 在我的答案中添加了一个示例。我的观点是,当您尝试将列限制为一组有效字符串中的一个时,不要有不必要的数字 ID。
  • 嗯,我明白了,使用外键约束有趣的概念,就像你说的那样,我将在我的系统中使用枚举,这意味着少了一个连接。也不错。
  • 小心在表中直接使用字符串值。它可以在某些情况下工作,但在其他情况下会失败。您必须担心可能的脏数据和可能更改值的需要,更不用说如果您有很多行的存储要求。
  • @John Yea 在这种情况下应该没问题,但我还有另一种情况,我存储了很多行,因此存储是一个因素。至于坏数据,外键约束会有所帮助,因为我可以保证审计表中的状态类型将与状态表中的内容相匹配,因此如果需要更改特定的状态应该相当简单。跨度>
【解决方案2】:

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

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

也就是说,确保完整性有很多价值。我喜欢用 BETWEEN 检查约束覆盖我所有的“枚举”列,这可以快速完成,并且在运行时甚至更快。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-12-24
    • 2014-01-24
    • 2016-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-09
    相关资源
    最近更新 更多