Reputation: 4053
Need constrain that will refuse insert/update if there is already some row with same value in column A
but different value in B
.
So:
Insert TableName(A, B) Values(x, y)
Insert TableName(A, B) Values(x, y)
Insert TableName(A, B) Values(x, z)
Will fail on the third inser as y =/=z. Or even on the first insert if there was already row (x, w) in the table.
On the other hand those inserts are valid:
Insert TableName(A, B) Values(c, y)
Insert TableName(A, B) Values(d, y)
Last remark. Data won't be normalized. Non normalized form is a feature not a bug. That's why I ask for constrain.
SQL Server 2008R2.
Upvotes: 1
Views: 45
Reputation: 239764
You can achieve this with an indexed view:
create table dbo.T (
A char(1) not null,
B char(1) not null
)
go
create view dbo.V_T
with schemabinding
as
select
A,
B,
COUNT_BIG(*) as Cnt
from
dbo.T
group by
A,B
go
create unique clustered index IX_V_T on dbo.V_T (A)
go
Insert T(A, B) Values('x', 'y')
Insert T(A, B) Values('x', 'y')
Insert T(A, B) Values('x', 'z')
The third insert generates the error:
Msg 2601, Level 14, State 1, Line 1
Cannot insert duplicate key row in object 'dbo.V_T' with unique index 'IX_V_T'. The duplicate key value is (x).
The statement has been terminated.
And continuing:
Insert T(A, B) Values('c', 'y')
Insert T(A, B) Values('d', 'y')
Both execute fine.
The design of the V_T
table is such that it has one row for each unique A,B
combination (the COUNT_BIG(*)
is just a requirement to allow this to be an indexed view, we're not allowed to use DISTINCT
). We then simply put a unique index on the A
values. Therefore, this view can only contain one row for each possible A
value or the unique constraint will be violated.
Upvotes: 1
Reputation: 15987
You can use INSTEAD OF trigger (with fixes based on comments of @Damien_The_Unbeliever):
At first create a table:
CREATE TABLE temp (
A nchar(1),
B nchar(1)
);
Create trigger:
CREATE TRIGGER testtemp
ON temp
INSTEAD OF INSERT, UPDATE
AS
INSERT INTO temp
SELECT A,
B
FROM (
SELECT i.*,
DENSE_RANK() OVER (PARTITION BY i.A ORDER BY i.A,i.B) as DR
FROM inserted i
OUTER APPLY (
SELECT TOP 1 *
FROM temp
WHERE A = i.A
) t
WHERE t.b IS NULL OR t.B = i.B
) C
where dr = 1
DELETE t
FROM temp t
INNER JOIN deleted d
ON d.A=t.A and d.B=t.B;
Then run:
Insert temp(A, B) Values
('x','y'),
('x','y'),
('x','z'),
('c','y'),
('d','y'),
('a','b'),
('a','c');
Output:
A B
a b
c y
d y
x y
x y
Upvotes: 2