T-SQL Unique Constraint WHERE AnotherColumn = Part

2019-08-24 04:14发布

Consider a link table with the following columns:

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

The system allows each Person and Location to be configured independently. Once configured, each Person can be linked to at most one Location. If a Person moves to a new Location, the link is to be deactivated, not deleted, so that the system knows when the Person was last linked to a particular Location. A Person can have any number of inactive links, but at most one active link. A Location can have any number of Persons actively linked to it.

How would I add a constraint to this table to prevent a second active link from being created for a Person when one already exists?

Edit: I thought this was a 2008 box... turns out it's 2005, so filtered indexes won't work.

4条回答
虎瘦雄心在
2楼-- · 2019-08-24 04:17

Constraints do not work across multiple rows, so you will need an INSERT/UPDATE trigger to enforce only one active record for a group of records with the same PersonID and LocationID.

查看更多
beautiful°
3楼-- · 2019-08-24 04:37

Rather than a linking table, have a link to Location ID on the Person table, as SilverSkin suggests. Now, if you want a list of inactives, add a trigger to the Person table to insert into a history table (a modification of your linking table) every time the location is changed (<> the last history table entry / one does not exist for the person). The link in the Person table gives the active link, while the history table gives the history and (should a person ping-pong between locations) an indication of the history of locations rather than a list of inactives.

查看更多
做自己的国王
4楼-- · 2019-08-24 04:37

foreign key references from tblPerson to PersonID, from tblLocation to LocationID, and a joint key on PersonId and LocationId to make sure that they are unique together.

查看更多
女痞
5楼-- · 2019-08-24 04:40

Using an indexed view to implement a "filtered index" on versions of SQL Server predating 2008:

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

You'll need to have the right ANSI settings turned on for this.

查看更多
登录 后发表回答