简体   繁体   English

如何创建条件唯一约束

[英]How to create conditional unique constraint

Having a table: Table1 in which a column Code accepts nullables values how can we insure that values are unique for non nullable values except for codes that start with 'A' which can be duplicated maximum twice? 拥有一个表: Table1中的一列Code接受可为空的值,我们如何确保非以null的值的值是唯一的,除了以'A'开头的代码最多可重复两次?

Table1 表格1

Id |  Code
---------- 
1  |  NULL   --[ok]
2  |  A123   --[ok]
3  |  A123   --[ok]
4  |  B100   --[ok] 
5  |  C200   --[ok]
6  |  B100   --[not ok already used]
7  |  NULL   --[ok]

What i have tried is creating an indexed view, the solution work fine for NULL values but not for the second case i mentioned (skipped actualy) 我试过创建索引视图,该解决方案可以很好地处理NULL值,但不能解决我提到的第二种情况(实际上已跳过)

Create view v_Table_unq with schemabinding as( 
         select code from 
         dbo.Table1 
         where code is not null and code not like 'A%'
)
go
create unique clustered index unq_code on v_Table_unq(code)

Thanks for help 感谢帮助

Table Creation 表格创建

CREATE TABLE CheckConstraint
(
  Name VARCHAR(50),
)
GO

Function Creation 功能创造

create FUNCTION CheckDuplicateWithA() RETURNS INT AS BEGIN

  DECLARE @ret INT  =0 ;
  SELECT @ret = IsNull(COUNT(Name), 0) FROM CheckConstraint WHERE Name like '[A]%' group by Name having COUNT(name) >= 1;
  RETURN IsNUll(@ret, 0);
END;

GO

create FUNCTION CheckDuplicateOtherThenA() RETURNS INT AS BEGIN

  DECLARE @ret INT  =0 ;
  SELECT @ret = IsNull(COUNT(Name), 0) FROM CheckConstraint WHERE Name not like '[A]%' group by Name having COUNT(name) >= 1;
  RETURN IsNUll(@ret, 0);
END;

GO

Constraints 约束条件

alter TABLE CheckConstraint
  add CONSTRAINT CheckDuplicateContraintWithA CHECK (NOT (dbo.CheckDuplicateWithA() > 2));
go

alter TABLE CheckConstraint
  add CONSTRAINT CheckDuplicateConmstraintOtherThenA CHECK (NOT (dbo.CheckDuplicateOtherThenA() > 1));
go

Result Set 结果集

insert into CheckConstraint(Name)Values('b')  -- Passed
insert into CheckConstraint(Name)Values('b')  -- Failed

insert into CheckConstraint(Name)Values('a')  -- Passed
insert into CheckConstraint(Name)Values('a')  -- Passed
insert into CheckConstraint(Name)Values('a')  -- Failed

Why would you want a unique contraint? 你为什么要一个独特的约束? Why cant add this logic in the proc which inserts the data in the table?If you do not have a single point of insertion/updation etc?Why cant put it in instead of or after trigger?That would be much better as you can handle it well and could return proper errror messages.This will have less overhead than having a index view which will add to overhead.If you need unique constraint for the records which doesnt start with 'A' then you can have a persisted column and have a unique constraint on that. 为什么不能在将数据插入表的proc中添加此逻辑?如果您没有单点插入/更新等功能?为什么不能将其放置在触发器之外或之后?这会更好,因为您可以处理如果索引需要唯一的约束而不以'A'开头,则可以有一个持久化的列并有一个唯一的约束。

Off course you will have overhead of having persisted computed column with index..But if you just need unique contsraint you can use that.For values which starts with 'A' this could be a null value. 当然,您将不得不保留带有索引的计算列的开销。但是,如果您只需要唯一的约束,则可以使用它。对于以“ A”开头的值,它可以为空值。

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

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