在这里添加where子句是个好主意吗?

时间:2014-12-02 15:08:58

标签: sql sql-server sql-server-2012

我有一张带有一些列的表..说A,B& C和最后一列名为DeletedDate。它是一个可以为空的日期时间。

我在A,B&添加了一个独特的约束。 C.它工作正常,直到我发现了一个问题。添加删除日期后。我应该可以为同一个A,B和B添加新记录。 C值。但我不能因为独特的限制。

我在这里看到两个选项

  1. 在约束
  2. 中包含DeletedDate列
  3. 在约束中添加where子句,说Where DeletedDate is not NULL
  4. 我的问题:哪个选项更好&为什么呢?

3 个答案:

答案 0 :(得分:2)

选项2:唯一约束不能包含WHERE子句。但您可以改为使用 filtered index

CREATE UNIQUE INDEX a_b_c_UQ_when_DeletedDate_is_null
ON TableName
  (a, b, c) 
WHERE DeletedDate IS NULL ;

选项1:如果您只是在唯一约束中包含DeletedDate,那么有两个问题:

  • 一个小小的,如果SQL-Server实现了sql-Standard中的唯一约束,那将允许2行或更多行具有相同的a,b,c组合和null删除日期,所以两个或多个未删除的行可以共存,这与要求不符。当然,这不是当前实施的问题。如果SQL-Server将来决定更改实现,那么它可能只会成为一个,以符合标准。

  • 一个更重要的问题是,这样您就不允许有2行或更多行具有相同的a,b,c组合和相同的完全删除日期。在您的情况下,这不是一个严重的问题,因为DeletedDatedatetime而不是date。如果您尝试使用相同的语句/事务删除多个行,则可能只会带来一些困难。

答案 1 :(得分:1)

您可以将计算列用于唯一索引。如果1可用,则返回静态值,如DeletedDate,否则返回主键的负对应值。

CREATE TABLE [dbo].[Test](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [A] [int] NOT NULL,
    [B] [int] NOT NULL,
    [C] [int] NOT NULL,
    [DeletedDate] [datetime] NULL,
    [IsDeleted]  AS (case when [DeletedDate] IS NULL then (1) else  -(1)*[ID] end),
 CONSTRAINT [PK_Test] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

现在,您可以在A,B,C和IsDeleted上创建唯一索引。

答案 2 :(得分:0)

日期往往不是包含唯一索引/约束的好选择,因为它们具有有限的分辨率,并且您不会始终保证唯一值 - 如果您需要添加批量删除在路上一次性删除十件事情的功能?他们都会有相同的删除日期。

不幸的是,由于问题是(适当地)抽象地关注空问题,我不知道约束的用例是什么,所以我不能推荐另一种方法。但是,我会说" no"作为实际问题的答案,因为空问题只是具有唯一日期值的许多问题中的第一个。