使更多列数据唯一的约束
constraint to make further column data unique
我有一个 table 和一些数据。现在,我想将非唯一列设置为唯一列。
但问题是,我不想删除 table 中存在的重复数据,而是想限制要添加到 table 中的数据不唯一。
实用:
我有一个 table tbl,其中 name,age 作为列。
我在 table 中有如下数据:
name |age
-----------------------
kaushikC |21
mohan |27
kumar |29
mohan |31
karthik |55
karthik |76
现在我想让名称列唯一,而不删除 'mohan' 和 'karthik' 的重复条目。
如何写这样的约束
如果您的 table 中有一列允许您识别不想更改的记录,例如 identity
列或创建日期,您可以创建table 上的唯一过滤索引,在其 where
子句中指定它应仅包含 table.
中的其他记录
假设您有一个名为 id
:
的 identity
列
id | name |age
-----------------------
1 | kaushikC |21
2 | mohan |27
3 | kumar |29
4 | mohan |31
5 | karthik |55
6 | karthik |76
您可以在此 table 上创建一个唯一的过滤索引,该索引仅对 id
大于 6 的行有效:
CREATE UNIQUE INDEX UX_YourTable_Name_WhereIdGraterThanSix
ON YourTable (Name)
WHERE id > 6;
这将使您能够在 table 上保持其他名称的唯一性 - 但是,它不会阻止您为任何现有名称再插入一个副本 - 因此您可以插入另一个 mohan
或另一个 kumar
到 table(但只有一个)。
如果要排除所有重复项,包括现有行的重复项,最好的选择可能是使用 instead of
触发器进行插入和更新:
CREATE TRIGGER tr_YourTable ON YourTable
INSTEAD OF INSERT, UPDATE
AS
BEGIN
-- the statement that fired the trigger is an update statement
IF EXISTS(select 1 FROM deleted)
BEGIN
UPDATE T
SET name = I.Name
FROM YourTable AS T
JOIN Inserted AS I
ON T.Id = I.Id
WHERE NOT EXISTS
( -- make sure the name is unique
SELECT 1
FROM YourTable AS T1
WHERE T1.Name = I.Name
AND NOT EXISTS
( -- unless it is going to be updated
SELECT 1
FROM Deleted AS D
JOIN Inserted AS I
ON D.Id = I.Id
WHERE D.Id = T1.Id
AND T1.Name = D.Name
AND D.Name <> I.Name
)
)
END
ELSE -- the statement that fired the trigger is an insert statement
BEGIN
INSERT INTO YourTable(Name)
SELECT I.Name
FROM Inserted I
WHERE NOT EXISTS
( -- make sure the name is unique
SELECT 1
FROM YourTable AS T1
WHERE T1.Name = I.Name
)
END
END
我有一个 table 和一些数据。现在,我想将非唯一列设置为唯一列。 但问题是,我不想删除 table 中存在的重复数据,而是想限制要添加到 table 中的数据不唯一。
实用: 我有一个 table tbl,其中 name,age 作为列。 我在 table 中有如下数据:
name |age
-----------------------
kaushikC |21
mohan |27
kumar |29
mohan |31
karthik |55
karthik |76
现在我想让名称列唯一,而不删除 'mohan' 和 'karthik' 的重复条目。
如何写这样的约束
如果您的 table 中有一列允许您识别不想更改的记录,例如 identity
列或创建日期,您可以创建table 上的唯一过滤索引,在其 where
子句中指定它应仅包含 table.
假设您有一个名为 id
:
identity
列
id | name |age
-----------------------
1 | kaushikC |21
2 | mohan |27
3 | kumar |29
4 | mohan |31
5 | karthik |55
6 | karthik |76
您可以在此 table 上创建一个唯一的过滤索引,该索引仅对 id
大于 6 的行有效:
CREATE UNIQUE INDEX UX_YourTable_Name_WhereIdGraterThanSix
ON YourTable (Name)
WHERE id > 6;
这将使您能够在 table 上保持其他名称的唯一性 - 但是,它不会阻止您为任何现有名称再插入一个副本 - 因此您可以插入另一个 mohan
或另一个 kumar
到 table(但只有一个)。
如果要排除所有重复项,包括现有行的重复项,最好的选择可能是使用 instead of
触发器进行插入和更新:
CREATE TRIGGER tr_YourTable ON YourTable
INSTEAD OF INSERT, UPDATE
AS
BEGIN
-- the statement that fired the trigger is an update statement
IF EXISTS(select 1 FROM deleted)
BEGIN
UPDATE T
SET name = I.Name
FROM YourTable AS T
JOIN Inserted AS I
ON T.Id = I.Id
WHERE NOT EXISTS
( -- make sure the name is unique
SELECT 1
FROM YourTable AS T1
WHERE T1.Name = I.Name
AND NOT EXISTS
( -- unless it is going to be updated
SELECT 1
FROM Deleted AS D
JOIN Inserted AS I
ON D.Id = I.Id
WHERE D.Id = T1.Id
AND T1.Name = D.Name
AND D.Name <> I.Name
)
)
END
ELSE -- the statement that fired the trigger is an insert statement
BEGIN
INSERT INTO YourTable(Name)
SELECT I.Name
FROM Inserted I
WHERE NOT EXISTS
( -- make sure the name is unique
SELECT 1
FROM YourTable AS T1
WHERE T1.Name = I.Name
)
END
END