数据库设计首选项:在 SQL 2000 中使用 DateTime 和 BIT

发布于 2024-08-03 18:38:57 字数 770 浏览 3 评论 0原文

我需要通过示例来解释这一点:

是否有在数据库表中指定日期时间和位的最佳实践或首选项?

在我的数据库中,我有一个小部件表。我需要知道小部件是否“已关闭”及其“关闭日期”业务规则规定,如果小部件已关闭,则它必须有一个关闭日期。如果小部件未关闭,则它不应具有“关闭日期”。

为了设计这个,我可以执行以下操作:(

示例 1):

CREATE TABLE [Widget]
(
    [WidgetID] INT IDENTITY(1,1)
    ,[ClosedDate] DATETIME NULL
)

或(示例 2):

CREATE TABLE [Widget]
(
    [WidgetID] INT IDENTITY(1,1)
    ,[IsClosed] BIT NOT NULL CONSTRAINT [DF_Widget_IsClosed] DEFAULT (0)
    ,[ClosedDate] DATETIME NULL
)

我认为示例 1 更清晰,因为它少了一个需要担心的列。但是,每当我需要评估小部件是否已关闭时,我都需要一个额外的步骤来确定 ClosedDate 列是否不为空。

示例 2 会产生额外的开销,因为现在我必须保持 IsClosed 和 ClosedDate 值同步。

设计这样的东西时有最佳实践吗? 对于示例 2,查询表的性能是否会更高?我有什么理由应该选择一种设计而不是另一种设计?

注意:我将通过 ORM 工具以及存储过程访问该值。

I need to explain this by example:

Is there a best practice or preference for specifying a DateTime and BIT in a database table?

In my database I have a Widget table. I need to know if a widget is "Closed" and it's "Closed Date" Business rules say that if a widget is closed, it must have a closed date. If a widget is not closed, it should not have a "Closed Date".

To design this, I could do the following:

(Example 1):

CREATE TABLE [Widget]
(
    [WidgetID] INT IDENTITY(1,1)
    ,[ClosedDate] DATETIME NULL
)

or (Example 2):

CREATE TABLE [Widget]
(
    [WidgetID] INT IDENTITY(1,1)
    ,[IsClosed] BIT NOT NULL CONSTRAINT [DF_Widget_IsClosed] DEFAULT (0)
    ,[ClosedDate] DATETIME NULL
)

I think that Example 1 is cleaner because it is one less column to have to worry about. But, whenever I need to evaluate whether a Widget is Closed, I would need an extra step to figure out if the ClosedDate column IS NOT NULL.

Example 2 creates extra overhead because now I have to keep both the IsClosed and ClosedDate values in sync.

Is there a best practice when designing something like this?
Would querying the table be more performant for Example 2? Is there any reason why I should choose one design over the other?

Note: I would be accessing this value through an ORM tool as well as Stored Procedures.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

无妨# 2024-08-10 18:38:57

我认为选项 1 更好。数据完整性得到更好的保持(不可能有一个带有相反标记的关闭日期),在超大表的情况下占用更少的磁盘空间,并且查询仍然是高性能的并且对于队友来说是清晰易懂的。

I think that option 1 is better. Data integrity is better kept (impossible to have a closed date with a flag which says the inverse), takes less disk space in the case of extra large tables, and queries would still be performant and clear to understand for teammates.

Hello爱情风 2024-08-10 18:38:57

第一个更好。检查空值的成本很低,而保留单独的标志则可以有一个关闭日期但尚未关闭。

The first is better. Checking for null is cheap, whereas keeping a separate flag makes it possible to have a closed date yet not be closed.

离线来电— 2024-08-10 18:38:57

我认为您将 IsClosed 列作为计算列。

CREATE TABLE [Widget](    
[WidgetID] INT IDENTITY(1,1),
[ClosedDate] DATETIME NULL,
IsClosed AS CAST(CASE WHEN ClosedDate IS NULL THEN 0 ELSE 1 END AS BIT)
)

原因是您没有存储任何内容,现在可以编写应用程序代码和存储过程来使用此列。如果您的业务规则发生变化,您可以将其转换为真正的列,而无需更改其他代码。否则,您的应用程序代码和存储过程中将会散布业务逻辑。这样,它就只在 1 个地方。

最后,当您迁移到 SQL2005 时,您可以添加“Persisted”子句。因此,它将被存储,从而稍微提高性能,并且保持它们同步不会有问题。

I think you have the IsClosed column as a computed column.

CREATE TABLE [Widget](    
[WidgetID] INT IDENTITY(1,1),
[ClosedDate] DATETIME NULL,
IsClosed AS CAST(CASE WHEN ClosedDate IS NULL THEN 0 ELSE 1 END AS BIT)
)

The reason is that you are not storing anything and you can now code your application code and stored procs to use this column. If your business rule ever changes you can convert this into a real column and you will not need to change other code. Otherwise you will have business logic sprinkled throughout your application code and stored procs. This way, it is only in 1 place.

Finally, when you move to SQL2005 you can add the "Persisted" clause. So it will be stored increasing the performance slightly and you will not have an issue with keeping them in sync.

情定在深秋 2024-08-10 18:38:57

我不会将语义赋予 NULL。这样做会在您的业务逻辑中冒泡,您将得到类似的代码...

public class Widget
{
  // stuff

  public bool IsClosed
  {
    // what do you put here?
    // it was null in the db so you have to use DateTime.MinDate or some such.
    return( _closeDate == ?? );  
  }

  // more stuff
}

以这种方式使用 null 是不好的。 NULL(和 null)意味着“我不知道”。您正在为该答案赋予语义,而实际上您不应该这样做。关闭状态就是关闭状态,关闭日期就是关闭日期,不要合并。 (例如,上帝禁止您想要重新打开小部件,但仍然记得它最初关闭的时间。)

Eric Lippert 有一个 关于以这种方式使用 null (kidna) 的不错的博客文章

I would not assign semantic meaning to NULL. Doing so will bubble through your business logic and you will get code like ...

public class Widget
{
  // stuff

  public bool IsClosed
  {
    // what do you put here?
    // it was null in the db so you have to use DateTime.MinDate or some such.
    return( _closeDate == ?? );  
  }

  // more stuff
}

Using null in that fashion is bad. NULL (and null) mean "I don't know". You are assigning semantic meaning to that answer when in reality, you should not. The closed status is the closed status and the closed date is the closed date, don't combine them. (God forbid you ever want to re-open a Widget but still remember when it got closed in the first place, for example.)

Eric Lippert has a nice blog post on using null in this way (kidna) as well.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文