除了NULL之外,处理未知日期时间值的好策略是什么?

时间:2013-03-26 18:37:22

标签: sql-server-2008 relational-database database-normalization

我的数据库有3个表:Organization,User& OrganizationUserJunction。 OrganizationUserJunction表跟踪用户所属的组织,何时成为组织成员以及何时离开组织。 MemberFrom字段填充了已知日期,但MemberTo日期最初未知。我不喜欢在我的表中使用NULL值。

当我处理字符串字段时,我可以用'UNKNOWN'填充它们而不是NULL。我想用datetime列做类似的事情。除了null之外,处理具有未知值的SQL Server datetime列的好策略是什么?

6 个答案:

答案 0 :(得分:4)

以你所描述的例子为例。当前成员没有MemberTo日期,因此在表中不需要MemberTo日期的成员资格。将MemberTo日期放在前成员的表中(其中包含与不适用于当前成员的前成员关联的此属性和其他属性)。这样做不需要空值。

答案 1 :(得分:3)

另一个人提到的另一个选择是为两个日期列使用单独的表。 (重新阅读时,我看到无法模仿的@sqlvogel确实提到了这一点。我将把代码作为一个例子。如果@sqlvogel希望将它合并到他的答案中,我刚刚赞成,那对我来说没关系。我会的之后删除我的答案。)

create table org_users (
  org_id integer not null references organizations (org_id),
  user_id integer not null references users (user_id), 
  member_from date not null default current_date,
  primary key (org_id, user_id, member_from)
);

create table org_users_member_to (
  org_id integer not null, 
  user_id integer not null,
  member_from date not null,
  member_to date not null default current_date
    check (member_to > member_from),
  primary key (org_id, user_id, member_from),
  foreign key (org_id, user_id, member_from) 
    references org_users (org_id, user_id, member_from)
);

答案 2 :(得分:2)

这是一个合理的问题,我不确定你为什么会被投票。

至少根据Joe Celko的说法,正确的答案是使用9999-12-31作为你的结束日期。根据ISO 8601,这是官方的“时间结束”。

您还可以考虑使用专为此目的而设计的第6种普通形式(也称为锚定建模)。

答案 3 :(得分:1)

NULL有什么问题?如果NULL的实际原因很重要(例如心率NULL,因为他已经死了或因为我们还没有捕获它),请在单独的列中跟踪(可能是tinyint FK到一个名为dbo.DateIsNULLReasons table)的查找表。

对此的所有变通方法(“魔术”日期值,使用INT查找到必须具有NULL能力列的不同表格的所有日期,或者在那里存储魔术日期)看起来像黑客对我来说。

我认为你应该克服你对NULL s的厌恶。它们的存在是出于某种原因,例如指定值为unknown,是否喜欢,以及无论原因。

通过存储UNKNOWN代替NULL,您获得了什么?你知道表和任何二级索引需要多少额外空间吗?您是否觉得现在必须针对某些查询过滤该方案而烦恼?

答案 4 :(得分:1)

如何使用默认日期进行会员审核。说加入后5年。

或者,如果我们正在与商业组织打交道并且您捕获DOB和性别,那么您可以计算退休年龄。

就个人而言,我没有看到NULL的问题。在MemberTo date的上下文中,IS NULL =仍然是成员。它与默认值的用途完全相同,并且远不如填充的默认日期值复杂。

答案 5 :(得分:0)

我知道这是一个旧线程,但是我偶然发现了它。

应该避免使用null是一个好主意,尤其是对于DateTime

原因:SQL Server默认将null设置为1/1/1900之类。如果您有dateOfCasuality之类的用例,则需要包括特殊逻辑来处理与DOB相关的规则。

可能的解决方案:将ForeignKey关系与另一个包含日期的表一起使用。但这将增加架构的复杂性。但是,我绝不会尝试将其转换为字符串,因为这会导致编码梦night。