我使用SQL Server 2008中我有一个数据库表,看起来像这样(与不重要列ommitted):SQL服务器过滤索引唯一约束
CREATE TABLE [dbo].[ImageDocument_FaxProperties](
[FaxPropertyID] [int] PRIMARY KEY IDENTITY(1,1),
[Agent] [varchar](25) NULL,
[ParentImageDocumentId] [uniqueidentifier] NULL
)
我想创建一个约束,其中相同只要ParentImageDocumentIds在每一行上相同,代理就可以有多行,但代理不能有具有不同ParentImageDocumentIds的行。我知道这不是一个好的表格结构,但它的传统&我不允许改变它。 NULL ParentImageDocumentIds应该被认为是不同的。
例如:
PK Agent ParentImageDocumentId -This is ok
# person1 {D09C3900-0300} {.. other columns ..}
# person1 {D09C3900-0300} {.. other columns ..}
PK Agent ParentImageDocumentId -Check constraint prevents 2nd row insertion
# person1 NULL {.. other columns ..}
# person1 NULL {.. other columns ..}
PK Agent ParentImageDocumentId -Check constraint prevents 2nd row insertion
# person1 NULL {.. other columns ..}
# person1 {A13E5B21-93DE} {.. other columns ..}
PK Agent ParentImageDocumentId -Check constraint prevents 2nd row insertion
# person1 {D09C3900-0300} {.. other columns ..}
# person1 {A13E5B21-93DE} {.. other columns ..}
我不知道什么是写这个约束的最佳途径。代理商的独特索引不起作用,因为它们有时可以兼得。一个独特的Agent,ParentImageDocumentId将允许他们拥有不同的GUID,这是不好的。具有“WHERE ParentImageDocumentId IS NULL AND Agent IS NOT NULL”的筛选索引将用于防止出现双重NULL,但不能使用不同的GUID或NULL。
下面是两个工作解决方案,但我想知道是否有更好的方法。索引模式绑定视图允许我创建更复杂的过滤索引。另一种方法是使用函数的表级检查约束,这应该可行,但添加检查约束是超慢。我猜它正在为表中的每一行重新运行我的函数,但添加一个表级约束是不必要的,因为函数没有检查特定的行。有没有解决的办法?我倾向于索引视图,但想知道是否有替代方案(除了更改我的表结构)&哪个替代方案是最好的。
解决方案#1:
CREATE VIEW ImageDocument_FaxProperties_Assignments WITH SCHEMABINDING
AS
SELECT Agent, ParentImageDocumentId, COUNT_BIG(*) as numPages FROM dbo.ImageDocument_FaxProperties
WHERE Status IN ('PROC', 'LINKING')
AND Agent IS NOT NULL
GROUP BY Agent, ParentImageDocumentId
GO
CREATE UNIQUE CLUSTERED INDEX [IDX_ImageDocument_FaxProperties_Assignments_Unique] ON [ImageDocument_FaxProperties_Assignments] (Agent)
GO
解决方案2:
CREATE FUNCTION ImageDocument_FaxProperties_Assignments_CheckConstraint() RETURNS BIT
AS
BEGIN
DECLARE @Result BIT = 0;
WITH Assignments AS
(SELECT Agent, DENSE_RANK() OVER (PARTITION BY Agent ORDER BY ParentImageDocumentId) AS assignmentNum
FROM dbo.ImageDocument_FaxProperties
WHERE Status IN ('PROC', 'LINKING')
AND Agent IS NOT NULL
)
SELECT @Result = 1 FROM Assignments WHERE assignmentNum > 1
RETURN @Result
END
GO
ALTER TABLE [ImageDocument_FaxProperties]
ADD CONSTRAINT ImageDocument_FaxProperties_Assignments_Unique CHECK (dbo.ImageDocument_FaxProperties_Assignments_CheckConstraint() = 0)
FWIW,基于udf的解决方案导致我频繁死锁。过滤视图效果更好。 – Constantin