建模和规范化时如何处理空值?

问题描述 投票:2回答:2

我是SQL的新手(还在学习),我必须为场地创建一个数据库。用于活动房间的客户手册。问题是客户并不总是提供他们的姓名,电子邮件和电话号码。大多数时候,它的名称和电子邮件或姓名和电话。它很少全部3,但它发生了。我需要将它们中的每一个存储在各自的属性(名称,电子邮件,电话)中。但是他们给我信息的方式,我有很多空值。我可以用这些空值做什么?我被告知最好没有空值。之后我还需要规范化我的桌子。请给我任何建议。

postgresql null relational-database database-normalization
2个回答
3
投票

SQL根据其版本的3VL(3值逻辑)特别处理NULL。规范化和其他关系理论没有。但是,我们可以将SQL设计转换为关系设计并返回。 (这里假设没有重复的行。)

规范化发生在关系上,并且是根据不特别处理NULL的运算符来定义的。术语“normalization”有两个最常见的不同含义:将表放入“1NF”和“更高的NF(正常形式)”。 NULL不会影响“规范化为1NF”。 “归一化到更高的NF”将表格替换为连接回来的较小的表格。出于规范化的目的,除了SQL类型的值之外,您还可以将NULL视为可空列的域中允许的值。如果我们的SQL表没有NULL,那么我们可以将它们解释为关系和SQL连接等作为连接等。但是如果你分解组件之间共享可空列的位置然后意识到要重构SQL中的原始,你必须SQL连接同名列相等或均为NULL。并且您不希望在SQL数据库中使用这样的CK(候选键)。例如,您不能将其声明为SQL PK(主键),因为这意味着UNIQUE NOT NULL。例如,涉及可空列的UNIQUE约束允许在该列中具有NULL的多个行,即使这些行在每列中具有相同的值。例如,SQL FK中的NULL会使它们满足(以每种MATCH模式的各种方式),不会因为没有出现在引用的表中而失败。 (但DBMS与标准SQL特殊地不同。)

不幸的是,分解可能会导致所有CK包含NULL的表,因此我们没有任何内容可以声明为SQL PK或UNIQUE NOT NULL。唯一可靠的解决方案是转换为无NULL设计。在标准化之后,我们可能希望在组件中重新引入一些可空性。

在实践中,我们设法设计表,以便始终有一组无NULL的列,我们可以通过SQL PK或UNIQUE NOT NULL声明为CK。我们可以通过从表中删除并添加一个包含该列的表和一些无NULL的CK的列来删除不在所有无NULL的CK中的可空列:如果该列对于非在旧设计中的行然后在其中包含CK子行和列值的行在添加的表中;否则在旧设计中为NULL,并且添加的表中没有相应的行。当然,我们还必须修改从旧设计到新设计的查询。

我们总是可以通过一个设计来避免空值,这个设计添加了一个标志列,该标志列表示旧设计中先前可为空的列是否为NULL,如果是这样,那么该列就是我们为此类型选择的一个值。数据库。当然,我们还必须修改从旧设计到新设计的查询。

是否要避免NULL是一个单独的问题。对于具有任一设计的应用程序,您的数据库可能在某种程度上“更好”或“更差”。避免NULL背后的想法是it complicates the meanings of queries,因此与更多无NULL表的更多连接的复杂性相比,以一种反常的方式使查询变得复杂。 (通常通过将查询表达式中的NULL移除到尽可能接近它们的位置来管理这种反常。)

PS许多SQL术语(包括PK和FK)与关系术语不同。 SQL PK意味着更像超级密钥; SQL FK意味着更像外国超级钥匙; but it doesn't even make sense to talk about a "superkey" in SQL

由于SQL表与关系的相似性,涉及关系的术语被粗略地应用于表。但是,尽管你可以借用术语并赋予它们SQL的含义(值,表,超级键,CK,PK,FK,连接,谓词,NF,规范化等),你不能只用那些SQL的含义替换这些词的含义。 RM定义,定理或算法,并获得明智或真实的东西。此外,RM概念的SQL演示几乎从未实际告诉您如何将RM概念合理地应用于SQL数据库。他们只是嘲笑RM演示文稿,不知道他们是否使用SQL术语来使术语变得荒谬或无效。


2
投票

首先,数据库中的空值没有任何问题。它们完全是为了这个目的而制造的,其中属性是未知的。为了避免数据库中的空值,我认为这个建议毫无意义。

因此,您有三个(或四个)值 - 名称(第一个/最后一个),电子邮件地址和电话号码 - 标识客户端。您可以将它们放在表格中并向其添加约束,以确保始终至少填充其中一列,例如coalesce(name, email, phone) is not null。这样可以确保无法完全匿名预订。

根据您的解释,您是否始终从客户端获得相同的信息尚不清楚。那么客户是否可以预订一个房间给出他们的名字,之后他们会预订另一个房间给他们的电话呢?或者是否会在数据库中查找客户端,找到他们的姓名以及分配给他们的两个预订?在后一种情况下,您可以拥有一个客户表,其中包含您目前所获得的所有信息,并且预订将包含客户记录ID作为此数据的参考。在前一种情况下,您可能不希望拥有一个客户表,因为您无法确定两个客户端(Jane Miller和[email protected])实际上是两个不同的客户端还是仅一个客户端。

到目前为止我看到的表格:

  • 房间(room_id,...)
  • 场地(venue_id,...)
  • 客户端(client_id,名称,电子邮件,电话)
  • 预订(venue_id,room_id,client_id,...)
© www.soinside.com 2019 - 2024. All rights reserved.