【问题标题】:Unique constraint on multiple columns when any columns are not null当任何列不为空时对多列的唯一约束
【发布时间】:2020-10-10 00:56:11
【问题描述】:

我正在尝试在 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

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

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

【问题讨论】:

  • 您可以使用所需的 Where 子句创建视图,然后在其上创建唯一索引以强制执行此操作。过滤后的索引语法只允许<filter_predicate> ::= <conjunct> [ AND <conjunct> ]
  • 谢谢。我根据您的评论写了一个答案。 @马丁史密斯

标签: sql-server unique-constraint


【解决方案1】:

这有点笨拙,但如果重点是强制唯一性(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

【讨论】:

  • 它具有将约束/等保留在表本身内的优点。当其他编码人员需要使用它时,或者当您在 6 个月后再次使用它时,它会变得更容易。
【解决方案2】:

根据 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-10
    • 1970-01-01
    相关资源
    最近更新 更多