当任何列都不为空时,对多列的唯一约束

问题描述

我正在尝试在2列上添加唯一约束,该约束允许多个(null,null),但不允许多个("a",null)。我编写了以下sql语句,但出现错误

关键字“ with”附近的语法不正确

sql语句:

CREATE UNIQUE NONCLUSTERED INDEX [UQ] 
ON [dbo].[MyTable] ([Column_A],[Column_B])
WHERE [Column_A] IS NOT NULL OR [Column_B] IS NOT NULL
WITH (PAD_INDEX = OFF,STATISTICS_norECOmpuTE = OFF,SORT_IN_TEMPDB = OFF,IGnorE_DUP_KEY = OFF,DROP_EXISTING = OFF,ONLINE = OFF,ALLOW_ROW_LOCKS = ON,ALLOW_PAGE_LOCKS = ON) ON [PRIMARY];

但是在

 WHERE [Column_A] IS NOT NULL OR [Column_B] IS NOT NULL

当我将OR替换为AND时,就不再有语法错误。但是我想要的是OR逻辑,而不是AND,因为使用AND允许多个("a",null)条目。

那么为什么使用OR会出现不正确的语法错误?谢谢。

解决方法

这有点笨拙,但是如果要强制执行唯一性(NULL / NULL除外)并且您很高兴拥有两个索引,则可以通过将NOT NULL过滤器放在单独的索引上来实现,例如,

CREATE UNIQUE NONCLUSTERED INDEX
[UQ_A] ON [dbo].[MyTable]
(
    [Column_A],[Column_B]
)
WHERE [Column_A] IS NOT NULL
GO

CREATE UNIQUE NONCLUSTERED INDEX
[UQ_B] ON [dbo].[MyTable]
(
    [Column_A],[Column_B]
)
WHERE [Column_B] IS NOT NULL
GO

虽然不必进行唯一性检查,但您可能希望更改第二个索引中字段的顺序,以潜在地获得索引的其他优点(取决于在应用程序中如何使用这些字段-可能会更好在第一个索引中交换它们),例如

CREATE UNIQUE NONCLUSTERED INDEX
[UQ_B] ON [dbo].[MyTable]
(
    [Column_B],[Column_A] 
)
WHERE [Column_B] IS NOT NULL
GO
,

根据马丁·史密斯(Martin Smith)的评论,我认为我可以通过以下方式实现它:

CREATE VIEW [dbo].[TableAView]
WITH SCHEMABINDING AS
SELECT
[ColumnA] = [ColumnA],[ColumnB] = [ColumnB]
FROM [dbo].[TableA]
WHERE [ColumnA] IS NOT NULL OR [ColumnB] IS NOT NULL;
GO

CREATE UNIQUE CLUSTERED INDEX
[UQ] ON [dbo].[TableAView]
(
    [ColumnA],[ColumnB]
)
WITH (PAD_INDEX = OFF,STATISTICS_NORECOMPUTE = OFF,SORT_IN_TEMPDB = OFF,IGNORE_DUP_KEY = OFF,DROP_EXISTING = OFF,ONLINE = OFF,ALLOW_ROW_LOCKS = ON,ALLOW_PAGE_LOCKS = ON)
ON [PRIMARY];
GO