寻找有关哪些表约束必须实现唯一性的建议

时间:2017-12-13 08:19:45

标签: sql sql-server unique-constraint

在sql-server表中期望如下所示的数据:

具有 id1 的资源将是不同版本的条目,并且对于不同版本也可以具有不同的名称。

但是名称不能在资源之间共享。一旦id1使用NameX,其他资源就不能使用相同的名称。

请建议我可以定义的sql-table约束来实现这个目的:

Id   Name    Version
------------------
id1  Name1   1
id1  Name1   2
id1  NameA   3
id1  NameX   4
id2  Name2   1
id2  NameX   2      --invalid record, NameX is already used for id1

2 个答案:

答案 0 :(得分:3)

您可以使用带有几个唯一索引的索引视图来确保每个名称仅在视图中的每个id值出现一次,然后使完整的名称集唯一:

create table dbo.Ix (ID varchar(20) not null, Name varchar(20) not null, 
                     Version int not null)
go
create view dbo.DRI_Ix_Unique_Names
with schemabinding
as
    select
        Id,Name,COUNT_BIG(*) as Cnt
    from
        dbo.Ix
    group by
        ID,Name
go
create unique clustered index IX_DRI_IX_Unique_Names on dbo.DRI_Ix_Unique_Names (Id,Name)
go
create unique nonclustered index IX_DRI_IX_Unique_Names_Only on 
        dbo.DRI_Ix_Unique_Names(Name)
go
insert into dbo.Ix(ID,Name,Version) values
('id1','Name1',1)
go
insert into dbo.Ix(ID,Name,Version) values
('id1','Name1',2)
go
insert into dbo.Ix(ID,Name,Version) values
('id1','NameA',3)
go
insert into dbo.Ix(ID,Name,Version) values
('id1','NameX',4)
go
insert into dbo.Ix(ID,Name,Version) values
('id2','Name2',1)
go
insert into dbo.Ix(ID,Name,Version) values
('id2','NameX',2)

这导致五次成功插入后跟一个错误,因为最终的插入违反了非聚集的唯一索引。

我不确定版本列如何影响您的要求,并且未在任何约束中使用它。

答案 1 :(得分:0)

创建一个触发器,在插入新记录之前检查值的存在,如果记录存在则抛出错误

像这样

CREATE TRIGGER ti_CheckRecord
on YourTable before insert
begin

if exists(select 1 from inserted where exists(select 1 from yourtable where name = inserted.name and id <> inserted.id))
begin
 --write your error code here
end

end