Check constraints cannot directly reference other rows data. There are some techniques that try to use UDFs to get around this limitation but they tend to not work well. Especially in this case where I presume the insert of row 4 should also be blocked if it had a bowlerID of 165
since that would mean overs 2&3 shared a bowler.
Instead, we can implement this with a pair of views. I usually put DRI somewhere in the name of views like this to indicate that they're there for Declarative Referential Integrity reasons, not because I intend people to query them.
create table dbo.Bowling (
ID int not null,
OverNumber int not null,
BowlerID int not null,
InningsID int not null,
constraint PK_Bowling PRIMARY KEY (ID),
constraint UQ_Bowling_Overs UNIQUE (OverNumber,InningsID)
)
go
create view dbo.Bowling_DRI_SuccessiveOvers_Odd
with schemabinding
as
select
(OverNumber/2) as OddON,
BowlerID
from
dbo.Bowling
go
create unique clustered index UQ_Bowling_DRI_SuccessiveOvers_Odd on dbo.Bowling_DRI_SuccessiveOvers_Odd (OddON,BowlerID)
go
create view dbo.Bowling_DRI_SuccessiveOvers_Even
with schemabinding
as
select
((OverNumber+1)/2) as EvenON,
BowlerID
from
dbo.Bowling
go
create unique clustered index UQ_Bowling_DRI_SuccessiveOvers_Even on dbo.Bowling_DRI_SuccessiveOvers_Even (EvenON,BowlerID)
go
insert into dbo.Bowling(ID,OverNumber,BowlerID,InningsID) values
(1,1,150,1),
(2,4,160,1),
(3,3,165,1)
go
insert into dbo.Bowling(ID,OverNumber,BowlerID,InningsID) values
(4,2,150,1)
This final insert generates the error:
Msg 2601, Level 14, State 1, Line 37 Cannot insert duplicate key row
in object 'dbo.Bowling_DRI_SuccessiveOvers_Even' with unique index
'UQ_Bowling_DRI_SuccessiveOvers_Even'. The duplicate key value is (1,
150). The statement has been terminated.
Hopefully, you can see the trick I'm employing to make these views check your desired constraint - it's set up so that rows are paired with either their (logical, based on OrderNumber
) successor or predecessor based on dividing the OrderNumber
by two using integer maths.
We then apply unique constraints on these pairs and including the BowlerID
. Only if the same bowler bowls two successive overs will we generate more than one row with the same (OddON
/EvenON
) and BowlerID
values.