简体   繁体   English

SQL Server:两列的单个值上的唯一索引(!!!不组合)

[英]SQL Server: Unique Index on single values of two columns (!!! Not Combination)

I have a table for teams where each team has two codes. 我有一个团队表,每个团队有两个代码。 A code for teammembers and a code for the teamleader. 团队成员的代码和团队负责人的代码。

TeamId    Name     MemberCode    LeaderCode
--------------------------------------------
1         Team1    CodeXY        CodeXYZ
2         Team2    CodeAB        CodeBC
...

There are two unique indexes, one on MemberCode and one on LeaderCode securing that MemberCodes and LeaderCodes are unique. 有两个唯一索引,一个在MemberCode ,一个在LeaderCode上, LeaderCode确保MemberCodes和LeaderCodes是唯一的。

But how can I define the not only MemberCodes itself are unqiue, but MemberCodes and LeaderCodes? 但是,如何不仅定义MemberCodes本身是不合理的,还定义MemberCodes和LeaderCodes?

No MemberCode should be a LeaderCode. 任何MemberCode都不应该是LeaderCode。

Someone got an idea? 有人知道吗?

PS: A unique index on the two columns like Create Unique index UIDX_12 On tbl (MemberCode, LeaderCode) is no option! PS:两列上的Create Unique index UIDX_12 On tbl (MemberCode, LeaderCode)Create Unique index UIDX_12 On tbl (MemberCode, LeaderCode)

With this data structure, I think you would have to have a trigger. 有了这种数据结构,我认为您将必须有一个触发器。

You can reformat the data, so you have one table and (at least) three columns: 您可以重新格式化数据,因此您只有一个表和(至少)三列:

  • TeamId TeamId
  • Code
  • CodeType CODETYPE

Then you can add constraints: 然后,您可以添加约束:

  • codetype is only 'member' or 'leader' codetype类型仅是“成员”或“领导者”
  • code is unique code是唯一的
  • teamid is in the teamid table teamid在teamid表中
  • teamid / codetype is unique teamid / codetype是唯一的

This will allow you to store exactly one of each of these values for each team (assuming that the values are not NULL ). 这将允许您为每个团队准确存储每个值中的一个(假设这些值不是NULL )。

In a create table statement, this might look something like: 在create table语句中,这可能类似于:

create table . . .
    check codetype in ('member', 'leader'),
    unique(code),
    teamid references teams(teamid),
    unique (teamid, codetype)
    . . .

You can enforce this constraint with an indexed view . 您可以使用索引视图强制执行此约束。 Something like: 就像是:

create table dbo.MColumnUnique (
    MemberName int not null,
    LeaderName int not null
)
go
create table dbo.Two (ID int not null primary key,constraint CK_Two_ID CHECK (ID in (1,2)))
go
insert into dbo.Two(ID) values (1),(2)
go
create view dbo.MColumnUnique_Enforcer (Name)
with schemabinding
as
    select
        CASE WHEN ID = 1 THEN MemberName ELSE LeaderName END
    from
        dbo.MColumnUnique
            cross join
        dbo.Two
go
create unique clustered index IX_MColumnUnique_Enforcer on dbo.MColumnUnique_Enforcer (Name)
go
insert into dbo.MColumnUnique (MemberName,LeaderName) values (1,2),(3,4) --Works
go
insert into dbo.MColumnUnique (MemberName,LeaderName) values (4,5) --Fails
go
insert into dbo.MColumnUnique (MemberName,LeaderName) values (6,6) --Fails

Where hopefully you can see the parallels between my above structure and your tables. 希望在哪里可以看到我上面的结构和表之间的相似之处。

dbo.Two is just a generally helpful helper table that contains exactly two rows, and is used to perform a limited unpivot on the data into a single column. dbo.Two只是一个非常有用的帮助程序表,它仅包含两行,用于对数据执行有限的数据透视,使其变成一列。

You could do it with a trigger, but I would use a CHECK CONSTRAINT. 您可以使用触发器来完成此操作,但是我将使用CHECK CONSTRAINT。

Create a function that takes a varchar parameter (or whatever the datatype you use for MemberCode and LeaderCode), and returns a bit: 0 if there is no LeaderCode or MemberCode that matches the parameter value, or 1 if there is a match. 创建一个使用varchar参数(或您用于MemberCode和LeaderCode的数据类型)的函数,然后返回一个位:如果没有与参数值匹配的LeaderCode或MemberCode,则返回0;如果存在匹配项,则返回1。

Then put a check constraint on the table that specifies: 然后将检查约束放在指定以下内容的表上:

  • MemberCode <> LeaderCode AND MemberCode <> LeaderCode AND
  • YourFunction(MemberCode) = 0 AND YourFunction(MemberCode)= 0 AND
  • YourFunction(LeaderCode) = 0 YourFunction(LeaderCode)= 0

EDIT based on Damien's comment: 根据Damien的评论进行编辑:

To prevent the function from including the row you just added, you need to also pass the [code] column (which you say is UNIQUE), and not count the row with that value for [code]. 为了防止该函数包括您刚刚添加的行,您还需要传递[code]列(您说这是UNIQUE),并且不将具有该值的行计入[code]。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM