如果A
列中的某些行具有相同的值但B
中的值不同,则需要限制拒绝插入/更新。
所以:
Insert TableName(A, B) Values(x, y)
Insert TableName(A, B) Values(x, y)
Insert TableName(A, B) Values(x, z)
第三 inser将失败,因为y = / = z。或者甚至在第一次插入时,如果表中已经有行(x,w)。
另一方面,这些插入有效:
Insert TableName(A, B) Values(c, y)
Insert TableName(A, B) Values(d, y)
最后一句话。数据不会被标准化。非规范化表单是一个功能而不是错误。这就是我要求约束的原因。
SQL Server 2008R2。
答案 0 :(得分:2)
您可以使用INSTEAD OF触发器(根据@Damien_The_Unbeliever的评论进行修复):
首先创建一个表:
CREATE TABLE temp (
A nchar(1),
B nchar(1)
);
创建触发器:
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;
然后运行:
Insert temp(A, B) Values
('x','y'),
('x','y'),
('x','z'),
('c','y'),
('d','y'),
('a','b'),
('a','c');
输出:
A B
a b
c y
d y
x y
x y
答案 1 :(得分:1)
您可以使用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')
第三个插入生成错误:
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.
继续:
Insert T(A, B) Values('c', 'y')
Insert T(A, B) Values('d', 'y')
两者都执行得很好。
V_T
表的设计使得每个唯一的A,B
组合都有一行(COUNT_BIG(*)
只是允许它成为索引视图的一个要求,我们'不允许使用DISTINCT
)。然后,我们只在A
值上添加一个唯一索引。因此,此视图对于每个可能的A
值只能包含一行,否则将违反唯一约束。