anouar.bagari
anouar.bagari

Reputation: 2104

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

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)

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

Upvotes: 0

Views: 4547

Answers (2)

user1499112
user1499112

Reputation:

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

Upvotes: 2

Gulli Meel
Gulli Meel

Reputation: 891

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.

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.

Upvotes: -1

Related Questions