代码之家  ›  专栏  ›  技术社区  ›  Mehrdad Afshari

如何仅在日期时间的日期部分创建唯一约束?

  •  10
  • Mehrdad Afshari  · 技术社区  · 15 年前

    我正在写一个非常简单的博客引擎供自己使用(因为我遇到的每个博客引擎都太复杂了)。我希望能够通过它的URL来唯一地识别每个帖子,就像 /2009/03/05/my-blog-post-slug . 为了在数据层中完成它,我希望在 (Date, Slug) 哪里 Date 只是合成日期的日期部分(忽略日期时间)。我自己也有一些想法(像另一个专栏,可能是计算出来的,只保留日期部分),但是我来了解解决这个问题的最佳实践是什么。

    我怀疑SQL Server版本在这里很重要,但据记录,我在2008 Express上(我很欣赏更便携的解决方案)。

    表模式:

    create table Entries (
        Identifier int not null identity,
        CompositionDate datetime not null default getdate(),
        Slug varchar(128) not null default '',
        Title nvarchar(max) not null default '',
        ShortBody nvarchar(max) not null default '',
        Body nvarchar(max) not null default '',
        FeedbackState tinyint not null default 0,
        constraint pk_Entries primary key(Identifier),
    
        constraint uk_Entries unique (Date, Slug) -- the subject of the question
    )
    

    所选解决方案:

    我认为马克的解决方案更合适,考虑到这个问题是关于2008年。但是,我将使用整数方法(但不使用 INSERT S,因为它不能保证数据的完整性;我将使用一个预计算的整数列,因为我认为从客户机(在查询中)处理整数比较容易。

    谢谢大家。

    create table Entries (
        Identifier int not null identity,
        CompositionDate smalldatetime not null default getdate(),
        CompositionDateStamp as cast(year(CompositionDate) * 10000 + month(CompositionDate) * 100 + day(CompositionDate) as int) persisted,
        Slug varchar(128) not null default '',
        Title nvarchar(max) not null default '',
        ShortBody nvarchar(max) not null default '',
        Body nvarchar(max) not null default '',
        FeedbackState tinyint not null default 0,
        constraint pk_Entries primary key(Identifier),
        constraint uk_Entries unique (CompositionDateStamp, Slug)
    )
    go
    
    4 回复  |  直到 15 年前
        1
  •  13
  •   marc_s dmck    15 年前

    好吧,在SQLServer2008中,有一个新的数据类型叫做“日期”,您可以使用该列并在其上创建索引。

    当然,您也可以将“日期”类型的计算列添加到表中,只需将日期时间列的日期部分填充到该计算列中,使其持久化,并对其进行索引。应该工作得很好!

    就像这样:

    ALTER TABLE dbo.Entries
       ADD DateOnly as CAST(CompositionDate AS DATE) PERSISTED
    
    CREATE UNIQUE INDEX UX_Entries ON Entries(DateOnly, Slug)
    

    马克

        2
  •  2
  •   K. Brian Kelley    15 年前

    既然您是2008年的,请按照Marc的建议使用日期数据类型。否则,一个更简单的解决方案是有一个非计算列(这意味着您必须在插入时填充它),它使用格式为YYYYMMDD的日期。这是一种整数数据类型,体积小,易于使用。

        3
  •  1
  •   Chris Shaffer    15 年前

    对于SQL2005,您可以做与Marc_推荐的基本相同的事情,只需使用标准的日期时间。它看起来像这样(这里是未测试的代码):

    ALTER TABLE Entries ADD
        JustTheDate AS DATEADD(day, DATEDIFF(day, 0, CompositionDate), 0) NOT NULL PERSISTED
    

    然后在上创建索引(justthedate,slug)

    注意:这里的dateadd/datediff语句只计算合成日期。

        4
  •  0
  •   Kristen    15 年前

    多年来,我们在SQL Server中的计算列出现了各种各样的问题,因此我们不再使用它们。

    您可以使用一个只有日期列的视图-并在该视图的列上放置一个唯一索引。

    (一个可能有用的副作用是,您可以让视图排除一些行,这样您就可以实现“dateColumn必须是唯一的,但在dateColumn为空的情况下排除”)。

    现有的compositionDate列可以拆分为两个字段-compositionDate和compositionTime-以及一个检索视图,如果需要,可以将它们重新连接在一起-这样就可以在仅日期列上使用本机索引。

    (这可以在SQL 2005和更早的版本中使用date time实现——尽管在日期或时间上有点浪费,但不能同时使用两者)

    最后,您可以有一个insert/update触发器,它强制不存在具有重复复合数据的其他记录(仅限日期部分)