我的数据库有3个表:Organization,User& OrganizationUserJunction。 OrganizationUserJunction表跟踪用户所属的组织,何时成为组织成员以及何时离开组织。 MemberFrom字段填充了已知日期,但MemberTo日期最初未知。我不喜欢在我的表中使用NULL值。
当我处理字符串字段时,我可以用'UNKNOWN'填充它们而不是NULL。我想用datetime列做类似的事情。除了null之外,处理具有未知值的SQL Server datetime列的好策略是什么?
答案 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。