11

我正在编写一个非常简单的博客引擎供自己使用(因为我遇到的每个博客引擎都太复杂了)。我希望能够通过其 URL 来唯一标识每个帖子,例如/2009/03/05/my-blog-post-slug. 为了在数据层中完成它,我想创建一个复合唯一约束,以限制组合日期的日期部分(忽略一天中的时间)在(Date, Slug)哪里。Date我自己有一些想法(比如另一列,可能是计算出来的,只包含日期部分),但我来到 SO 是为了知道解决这个问题的最佳实践是什么。

我怀疑 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 年,我认为 marc 的解决方案更合适。但是,我将使用整数方法(但不使用INSERTs,因为它不能确保数据的完整性;我将使用预先计算的整数列)因为我认为使用来自客户端的整数事物(在查询中)更容易。

谢谢你们。

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

4 回答 4

13

好吧,在 SQL Server 2008 中,有一个名为“DATE”的新数据类型——您可以使用该列并在其上创建索引。

当然,您也可以将“DATE”类型的计算列添加到您的表中,只需将 DATETIME 列的日期部分填充到该计算列中,使其成为 PERSISTED,然后对其进行索引。应该工作得很好!

像这样的东西:

ALTER TABLE dbo.Entries
   ADD DateOnly as CAST(CompositionDate AS DATE) PERSISTED

CREATE UNIQUE INDEX UX_Entries ON Entries(DateOnly, Slug)

马克

于 2009-03-06T21:55:54.317 回答
2

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

于 2009-03-06T22:10:26.793 回答
1

对于 SQL 2005,您可以执行 marc_s 推荐的基本相同的操作,只需使用标准 DateTime。它看起来像这样(此处未经测试的代码):

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

然后在 (JustTheDate, Slug) 上创建您的索引

注意:那里的 DATEADD/DATEDIFF 语句只计算 CompositionDate 的日期。

于 2009-03-06T22:01:37.220 回答
0

多年来,我们在 SQL Server 中遇到了各种计算列问题,因此我们已经停止使用它们。

您可以将 VIEW 与仅用于日期的列一起使用 - 并在该 VIEW 的列上放置一个唯一索引。

(一个可能有用的副作用是您可以让 VIEW 排除某些行 - 因此您可以实现诸如“DateColumn 必须是唯一的,但排除 WHERE DateColumn IS NULL)之类的东西

现有的 CompositionDate 列可以拆分为两个字段 - CompositionDate 和 CompositionTime - 以及一个检索视图,如果需要,可以将它们重新组合在一起 - 然后允许在仅日期列上使用本机索引

(这可以在 SQL 2005 和更早的版本中使用 DateTime 来实现——尽管对于日期或时间来说有点奢侈,而不是两者)

最后,您可以有一个 INSERT / UPDATE 触发器,该触发器强制不存在具有重复 CompositionDate 的其他记录(仅限日期部分)

于 2009-03-08T12:42:14.380 回答