【问题标题】:T-SQL Unique Constraint WHERE AnotherColumn = ParticularValueT-SQL 唯一约束 WHERE AnotherColumn = ParticularValue
【发布时间】:2010-11-04 14:10:06
【问题描述】:

考虑一个包含以下列的链接表:

PersonID int NOT NULL
LocationID int NOT NULL
Active bit NOT NULL
...

系统允许独立配置每个人员和位置。配置后,每个人最多可以链接到一个位置。如果一个人移动到一个新位置,链接将被停用,而不是删除,以便系统知道该人最后一次链接到特定位置的时间。一个人可以有任意数量的非活动链接,但最多有一个活动链接。一个 Location 可以有任意数量的 Person 主动链接到它。

当一个人已经存在时,我如何向该表添加一个约束以防止为一个人创建第二个活动链接?

编辑:我以为这是 2008 年的盒子……结果是 2005 年,所以过滤索引不起作用。

【问题讨论】:

标签: sql sql-server sql-server-2005 tsql


【解决方案1】:

使用索引视图在 2008 年之前的 SQL Server 版本上实现“过滤索引”:

CREATE VIEW vOnlyOneActive
AS
  SELECT PersonID
  FROM <underlying table>
  WHERE Active = 1
GO
CREATE UNIQUE CLUSTERED INDEX IX_vOnlyOneActive on vOnlyOneActive (PersonID)
GO

您需要为此启用正确的ANSI settings

【讨论】:

    【解决方案2】:

    正如 SilverSkin 所建议的那样,在 Person 表上拥有指向 Location ID 的链接,而不是链接表。现在,如果您想要一个不活动列表,请在 Person 表中添加一个触发器,以便在每次更改位置时插入历史表(链接表的修改)(最后一个历史表条目/一个不存在为人)。 Person 表中的链接给出了活动链接,而历史表给出了历史和(如果一个人在位置之间乒乓球)位置历史的指示,而不是非活动列表。

    【讨论】:

    • 我喜欢你的想法。不幸的是,我被我所拥有的模式所困。 :)
    • 更多的是遗憾。我也喜欢这个。 :)
    【解决方案3】:

    约束不适用于多行,因此您需要INSERT/UPDATE trigger 来为具有相同PersonIDLocationID 的一组记录强制执行一个活动记录。

    【讨论】:

    • 我之前没有使用过触发器...在这里最好使用什么/什么样的触发器?
    • 当您编写该触发器时,请确保您完成了它以便它可以处理多行插入或删除,触发器一次不会处理一行。
    【解决方案4】:

    从 tblPerson 到 PersonID、从 tblLocation 到 LocationID 的外键引用,以及 PersonId 和 LocationId 上的联合键,以确保它们一起是唯一的。

    【讨论】:

    • 这样,仍然可能有两行具有相同的 PersonID、不同的 LocationID,并且都 Active = 1,这是不允许的。
    • 是的。那你可以考虑把 locationId 和 active bit 添加到 person 表中,这样每人只允许一个位置...
    • 这将完成约束工作。但是这样系统就不会记录一个人最后一次链接到一个位置的时间,这也是一个要求。 :)
    • 这取决于,如果你将 locationActive = 0 设置在一个人身上,你仍然会得到位置信息,直到下一次。啊,我明白了,你还想保存非活动链接?对,明白了。
    猜你喜欢
    • 1970-01-01
    • 2021-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-24
    相关资源
    最近更新 更多