有一个表格Table1
,其中列Code
接受nullables值,我们怎样才能确保这些值对于不可为空的值是唯一的,除了以'A'
开头的代码可以是重复最多两次?
表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]
我试过创建一个索引视图,该解决方案适用于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)
感谢您的帮助
答案 0 :(得分:2)
CREATE TABLE CheckConstraint
(
Name VARCHAR(50),
)
GO
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
alter TABLE CheckConstraint
add CONSTRAINT CheckDuplicateContraintWithA CHECK (NOT (dbo.CheckDuplicateWithA() > 2));
go
alter TABLE CheckConstraint
add CONSTRAINT CheckDuplicateConmstraintOtherThenA CHECK (NOT (dbo.CheckDuplicateOtherThenA() > 1));
go
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
答案 1 :(得分:-1)
为什么你想要一个独特的约束?为什么不能在proc中添加这个逻辑,在表中插入数据?如果你没有单点插入/更新等?为什么不能把它放在触发器之后或之后?这样会更好,因为你可以处理很好,并且可以返回正确的错误消息。这将比具有索引视图的开销更少,这将增加开销。如果您需要对不以'A'开头的记录的唯一约束,那么您可以拥有一个持久列并且具有对此的独特限制。
当然你会有持有带索引的计算列的开销。但是如果你只需要唯一的contsraint就可以使用它。对于以'A'开头的值,这可能是一个空值。