0

我是SQL新手(仍在学习),我必须为场地创建数据库。 一个活动房间的客户端。问题是客户并不总是提供他们的姓名,他们的电子邮件和他们的电话号码。大多数情况下,它是名称和电子邮件或姓名和电话。它很少全部3但它发生。 我需要将它们中的每一个存储在它们各自的属性(名称,电子邮件,电话)中。但他们给我他们的信息的方式,我有很多空值。 如何处理这些空值?我被告知最好不要有空值。之后我还需要对表格进行规范化。 请提出任何建议。在建模和规范化时如何处理空值?

+1

表AFAIK中的NULL值本身没有任何错误。更大的问题是你想用这些NULL值做什么?你希望数据库将它们替换为默认值吗?或者,也许你想在将数据传递给UI或客户端时以特殊方式处理NULL值? –

回答

2

SQL有NULL和3VL。规范化&其他关系理论没有。但是,我们可以将SQL设计转换为关系设计并返回。

实际上,我们设计了表格,以便在SQL PRIMARY KEY或UNIQUE NOT NULL中始终存在一组无NULL列,我们可以声明为CK(候选键)。我们可以通过从有问题的表中删除它,并添加一个包含该列和CK列的表,来摆脱不在CK中的可空列。如果该列对于旧设计中的行非空,则具有其CK字段和列值的行将放入新表中。否则它在旧设计中为NULL,并且新表中没有相应的行。当然,你也必须修改从旧设计到新设计的查询。

您可以通过设计添加一个标志列,该列标明行在旧设计中是否为NULL,并且如果是这样,您可以选择某个值用于此目的该类型在整个数据库中。当然,你也必须修改从旧设计到新设计的查询。

正常化发生在关系,其中不包含重复的行或NULL。术语“normalization”具有两个最常见的不同含义:将表格放入“1NF”和“更高的NF(正常形式)”。 NULL不影响“归一化到1NF”。 “规范化到更高的NFs”将其他表格替换为其他表格,其中每个表格都带有一些列,并将它们连接回来。出于规范化的目的,您可以将NULL视为一个额外的值,除了它的声明类型之外,它还允许在一个可为空的列的域中使用。但是如果你分解了组件之间共享可空列的地方,那么要意识到要在SQL中重建原始数据库,你必须加入同名或同时为NULL的列。你不会希望这样的CK在SQL数据库中。例如,非NULL的UNIQUE索引允许在同一列中有多个NULL的行,即使这些行在每个列中都具有相同的值。例如,无论列中有什么值作为FK,总是认为列中具有NULL的FK(外键)被满足。不幸的是,分解可能导致全部 CK包含NULL,因此您没有任何内容可以声明为SQL PRIMARY KEY或UNIQUE NOT NULL。唯一可靠的解决方案是转换为无空值设计,规范化,然后通过无损连接(现在为空无真)超级键组合表,将可空性放回到非CK列中的所需位置。

是否要避免NULL是一个单独的问题。无论哪种设计,您的数据库在某种程度上可能会对您的应用程序“更好”或“更糟糕”。避免NULL的想法是it complicates the meanings of queries,因此与使用更多无NULL表的更多连接的复杂性相比,以错误的方式使查询复杂化。 (通常通过消除查询表达式中的空值尽可能接近它们出现的位置来管理该变态。)

PS包括“PK”(主键)&“FK”(外键)的许多SQL术语不同于关系条款。SQL PK确实意味着更像superkey; SQL FK确实意味着更像外国超级密钥; but it doesn't even make sense to talk about a "superkey" in SQL

由于SQL表与关系的相似性,涉及关系的术语可以不经意地应用于表。但是,尽管你可以借用术语并赋予它们SQL的含义(表,超级键,CK,PK,FK,连接和谓词等),但是你不能仅仅将这些意义替换为其他RM定义或定理(NF ),规范化等),并得到明智或真实的东西。此外,RM概念的SQL演示几乎从未实际告诉您如何将RM概念完美应用于SQL数据库。他们只是鹦鹉RM演示文稿。 (“几乎”,是因为我希望有一些。)

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,...)