Reputation: 716
DB structure :
Table 1 (T1):
|I1|I2|I3|
|1 |1 |1 |
|2 |2 |2 |
.
.
Contraints:
Table 2 (T2):
|AI1|AI2|AI3|BI1|BI2|BI3|
|1 |1 |1 |2 |2 |2 |
.
.
Contraints:
What I want to Add
With currently mentioned constraints, there is still a possibility to add another row with such that
|2|2|2|1|1|1|
such possibility should also needs to be stopped.In other words,no combination that exists as AI1,AI2,AI3
cannot occur again as BI1,BI2,BI3
Is there any possible way to achieve this?
I thought of using trigger whenever new entry is added to T2
and later delete the newly added row, but that is not an elegant solution. Plus the code adding the row would assume that row has been added but in reality it is not persisted.
Upvotes: 1
Views: 125
Reputation: 239636
You can do this using a helper table and an indexed view:
create table dbo.Two (
N int not null,
constraint PK_Two PRIMARY KEY (N),
constraint CK_Two_Two CHECK (N in (1,2))
)
go
insert into dbo.Two(N) values (1),(2)
go
create view dbo.DRI_T2_MoreUnique
with schemabinding
as
select
CASE WHEN N=1 THEN AI1 ELSE BI1 END as I1,
CASE WHEN N=1 THEN AI2 ELSE BI2 END as I2,
CASE WHEN N=1 THEN AI3 ELSE BI3 END as I3
from
dbo.T2
inner join
dbo.Two
on
1=1
go
If you have a numbers table, you can use that as the helper rather than creating the special Two
table, just make sure that you're only selecting two rows from it within the view.
Basically, the helper table is there to assist us in performing a partial unpivot operation, but in a way that is compatible with indexed views.
Complete script:
create table dbo.T1 (
I1 int not null,
I2 int not null,
I3 int not null,
constraint PK_T1 PRIMARY KEY (I1,I2,I3)
)
go
insert into dbo.T1 (I1,I2,I3) values
(1,1,1),(2,2,2)
go
create table dbo.T2 (
AI1 int not null,
AI2 int not null,
AI3 int not null,
BI1 int not null,
BI2 int not null,
BI3 int not null,
constraint PK_T2 PRIMARY KEY (AI1,AI2,AI3,BI1,BI2,BI3),
constraint FK_T2_T1_A FOREIGN KEY (AI1,AI2,AI3)
references T1 (I1,I2,I3),
constraint FK_T2_T1_B FOREIGN KEY (BI1,BI2,BI3)
references T1 (I1,I2,I3)
)
go
insert into dbo.T2 (AI1,AI2,AI3,BI1,BI2,BI3) values
(1,1,1,2,2,2)
go
create table dbo.Two (
N int not null,
constraint PK_Two PRIMARY KEY (N),
constraint CK_Two_Two CHECK (N in (1,2))
)
go
insert into dbo.Two(N) values (1),(2)
go
create view dbo.DRI_T2_MoreUnique
with schemabinding
as
select
CASE WHEN N=1 THEN AI1 ELSE BI1 END as I1,
CASE WHEN N=1 THEN AI2 ELSE BI2 END as I2,
CASE WHEN N=1 THEN AI3 ELSE BI3 END as I3
from
dbo.T2
inner join
dbo.Two
on
1=1
go
create unique clustered index IX_DRI_T2
on dbo.DRI_T2_MoreUnique (I1,I2,I3)
go
insert into dbo.T2 (AI1,AI2,AI3,BI1,BI2,BI3) values
(2,2,2,1,1,1)
And the final insert produces this error:
Msg 2601, Level 14, State 1, Line 1
Cannot insert duplicate key row in object 'dbo.DRI_T2_MoreUnique' with unique index 'IX_DRI_T2'. The duplicate key value is (2, 2, 2).
The statement has been terminated.
Upvotes: 1
Reputation: 6709
Please refer the SQL CHECK Constraint. We can use a UDF in a CHECK Constraint to Validate a Column. For more info check here
Upvotes: 1