[英]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: 您可以重新格式化数据,因此您只有一个表和(至少)三列:
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: 然后将检查约束放在指定以下内容的表上:
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.