任何列不为空时对多列的唯一约束
Unique constraint on multiple columns when any columns are not null
我正在尝试在允许多个 (null, null)
但不允许多个 ("a", null)
的 2 列上添加唯一约束。我写了以下 SQL 语句,但出现错误
Incorrect syntax near the keyword '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
当我用 AND
替换 OR
时,不再有语法错误。但我想要的是 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
我正在尝试在允许多个 (null, null)
但不允许多个 ("a", null)
的 2 列上添加唯一约束。我写了以下 SQL 语句,但出现错误
Incorrect syntax near the keyword '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
当我用 AND
替换 OR
时,不再有语法错误。但我想要的是 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