当前位置: 首页 > 面试题库 >

具有NULL的唯一键

翟高明
2023-03-14
问题内容

这个问题需要一些假设的背景。让我们考虑一个employee有列的表namedate_of_birthtitlesalary,使用MySQL作为RDBMS。由于如果给定的某个人的名字和出生日期与另一个人相同,那么根据定义,他们就是同一个人(除非有两个巧合,即我们两个人分别于1809年2月12日出生,他们叫亚伯拉罕·林肯),所以我们将上的唯一键namedate_of_birth这意味着“不要将同一个人存储两次”。现在考虑以下数据:

id name        date_of_birth title          salary
 1 John Smith  1960-10-02    President      500,000
 2 Jane Doe    1982-05-05    Accountant      80,000
 3 Jim Johnson NULL          Office Manager  40,000
 4 Tim Smith   1899-04-11    Janitor         95,000

如果现在尝试运行以下语句,则该语句应该并且将失败:

INSERT INTO employee (name, date_of_birth, title, salary)
VALUES ('Tim Smith', '1899-04-11', 'Janitor', '95,000')

如果我尝试此操作,它将成功:

INSERT INTO employee (name, title, salary)
VALUES ('Jim Johnson', 'Office Manager', '40,000')

现在,我的数据将如下所示:

id name        date_of_birth title          salary
 1 John Smith  1960-10-02    President      500,000
 2 Jane Doe    1982-05-05    Accountant      80,000
 3 Jim Johnson NULL          Office Manager  40,000
 4 Tim Smith   1899-04-11    Janitor         95,000
 5 Jim Johnson NULL          Office Manager  40,000

这不是我想要的,但是我不能说我完全不同意发生的事情。如果说数学集

{'Tim Smith', '1899-04-11'} = {'Tim Smith', '1899-04-11'} <-- TRUE
{'Tim Smith', '1899-04-11'} = {'Jane Doe', '1982-05-05'} <-- FALSE
{'Tim Smith', '1899-04-11'} = {'Jim Johnson', NULL} <-- UNKNOWN
{'Jim Johnson', NULL} = {'Jim Johnson', NULL} <-- UNKNOWN

我的猜测是MySQL说:“由于我不 知道NULL出生日期的吉姆·约翰逊不在此表中,因此我将其添加。”

我的问题是:
即使date_of_birth并不总是知道如何防止重复?到目前为止,我想出的最好的办法是移到date_of_birth另一张桌子。但是,这样做的问题是,我最终可能会遇到两个出纳员,他们的名字,头衔和薪水相同,出生日期不同,而且没有重复的方式就无法存储它们。


问题答案:

唯一密钥的 基本属性是它必须是唯一的。使该键成为Nullable的一部分会破坏此属性。

有两种可能的解决方案来解决您的问题:

  • 一种方法(错误的方法)是使用一些魔术日期来表示未知数。这只是使您克服了DBMS的“问题”,但并不能从逻辑上解决问题。预期两个“约翰·史密斯”条目的生日不明的问题。这些家伙是同一个人还是独特的个人?如果您知道它们不同,那么您又回到了同样的旧问题-您的唯一密钥不是唯一的。甚至不要考虑分配一个完整的魔术日期来表示“未知”,这确实是通往地狱的道路。

  • 更好的方法是将EmployeeId属性创建为代理键。这只是您分配给 知道 唯一的个人的任意标识符。该标识符通常只是一个整数值。然后创建一个Employee表,以将EmployeeId(唯一的,不可为空的键)与您认为是依赖属性的属性相关联,在这种情况下,名称和出生日期(其中任何一个都可以为空)。在以前使用姓名/生日的任何地方使用EmployeeId代理键。这将向您的系统添加一个新表,但是以一种可靠的方式解决了未知值的问题。



 类似资料:
  • 问题内容: 我对数据库表中的唯一行有问题,现在可以这样做: 当我在所有列中使用UNIQUE属性时,即使第二个Moore名称不同,我也会插入第二个Moore错误:/ 如何使用UNIQUE(或INDEX?)在db表中执行类似的操作: 抱歉,如果问题很简单,但是我是sql的初学者,并且在使用UNIQUE之类的UNIQUE时找到一些好的示例时遇到问题:/或者也许我必须在插入新行之前从db中选择一个表并检查

  • 问题内容: 我注意到在具有UNIQUE约束的列中可以有NULL值: 在某些情况下会产生任何问题吗? 问题答案: 尽管以下内容解决了多个空值,但除了可能的数据库/ SQL可移植性之外,它 没有 解决与这种设计相关的任何“问题”,因此,它可能 不 应该被视为答案,在此仅作参考。 这实际上在SQLite常见问题解答中进行了介绍。这是一种设计选择-SQLite(与SQL Server不同)选择了多个NUL

  • 问题内容: 会根据其位置而不是其值来生成其元素被视为唯一的元素。所以基本上我想避免重复这样的事情: 之后的过滤是不可能的,因为在我的情况下,排列的数量太大。 有人知道合适的算法吗? 非常感谢你! 编辑: 我基本上想要的是以下内容: 这是不可能的,因为sorted创建列表并且itertools.product的输出太大。 抱歉,我应该已经描述了实际问题。 问题答案: 结果: 编辑(这是如何工作的):

  • 问题内容: 考虑以下代码: 程序的输出为: 这里,键如何相互关联。是否所有三个都分配给相同的哈希码?如果是,为什么? 由于这三个值看起来都不同,因此一个值的更改会更改另一个值。这是否意味着只将一个密钥项输入 到任一密钥中,因为所有密钥项都被视为相同的密钥。 问题答案: 当将 null 作为键传递并且null作为特殊情况处理时,不会调用哈希码。 放置方法 将 null 键放在存储区 0中, 并将 n

  • 我正在运行Postgres 9.5,并试图基于3个字段创建一个唯一的约束。我遇到的问题是,其中两列可以为NULL,因此这些字段为NULL的行不会违反唯一约束。我的目标是将其作为一个约束,因为我正在尝试更新冲突(UPSERT)。 桌子的结构是这样的 我在这里发现了另一个问题,我可以按照以下方式做一些事情 我不确定在where子句中有两个字段时这是否真的有效,但如何在冲突时调用这个唯一索引呢? 或者我

  • 问题内容: 我想向现有表添加复杂的唯一键。主要从4个字段包含(,,,)。但是表具有非唯一行。我知道我可以删除所有重复的日期,然后再添加复杂的密钥。 也许存在另一种无需搜索所有重复数据的解决方案。(例如添加唯一的忽略等)。 我搜索了UPD,如何删除重复的mysql行-我认为这是一个很好的解决方案。 仅使用MySQL查询删除重复项? 问题答案: 您可以按照yAnTar的建议进行 要么 您可以添加约束