Null 或空字符串——一个比另一个更好表示表列中没有数据?(我专门使用 MySQL,但我认为这是与系统无关的。)使用其中一个是否有主要优点/缺点,或者仅仅是程序员的偏好?
16 回答
我强烈不同意所有说无条件使用 NULL 的人。允许列为 NULL 会引入额外的状态,如果您将列设置为 NOT NULL,则不会出现这种状态。如果您不需要附加状态,请不要这样做。也就是说,如果你想不出空字符串的含义和null的含义的区别,那么将该列设置为NOT NULL,并使用空字符串来表示空。以两种不同的方式表示同一事物是一个坏主意。
大多数告诉您使用 NULL 的人还举了一个示例,其中 NULL 的含义与空字符串不同。在这些例子中,他们是对的。
然而,大多数时候,NULL 是一种不必要的额外状态,它只会迫使程序员不得不处理更多的情况。正如其他人所提到的,Oracle 不允许这种额外的状态存在,因为它将 NULL 和空字符串视为同一件事(在 Oracle 中不允许将空字符串存储在不允许 null 的列中)。
空值。空字符串不是“无数据”,而是恰好为空的数据。
Null 更好 "" 实际上代表数据,它不会在您的代码中注册相同
在关系数据库模型的上下文中,null 表示“无值”或“未知值”。它的存在正是您描述的目的。
更新:对不起,我忘了补充一点,虽然大多数(全部?)RDMBS 对 null 使用相同的定义,但 null 的处理方式存在细微差别。例如,MySQL 和 Oracle 允许在一个 UNIQUE 列(或一组列)中有多个空值,因为空值不是一个值,不能被认为是唯一的(空值!=空值)。但我上次使用 MS SQL Server 时,它只允许一个空值。因此,您可能需要考虑 RDBMS 行为,以及相关列是否会受到约束或索引。
两者都不。将数据的缺失表示为关系中元组的缺失。
出于性能原因,您可能希望避免在某些 RDBMS 中进行连接,但尝试设计模型,以便可能丢失的信息处于单独的关系中。
以下是来自 MySQL 网站的几个链接:
http://dev.mysql.com/doc/refman/5.0/en/problems-with-null.html
http://dev.mysql.com/doc/refman/5.0/en/working-with-null.html
我确实读过一次,NULL
值是 2 位,而空字符串只有 1 位。NULL
99% 的情况下这不会有任何区别,但是在一个非常大的表中,如果或无关紧要,那么如果这是真的''
,那么使用它可能会更好。''
始终使用 NULL。考虑一下“我不知道这个人的电话号码是什么”(NULL)和“这个人把它留空”(空白)之间的区别。
为工作使用正确的工具。NULL 可以表示(还)没有提供值,也可以表示没有值是适用的。
但是空字符串也是信息。它可以表示一个值是适用的,并且是给定的,但它恰好是一个空字符串。
允许列同时包含 NULL 和 '' 使您有机会区分这些情况。无论如何,用一个来表示另一个是不好的。
请注意,在字符串连接中,任何与 NULL 结合的东西都会产生 NULL。例如: CONCAT(NULL, 'foo') 产生 NULL。如果要将 NULL 转换为 SQL 表达式中的某个默认值,请学习使用 COALESCE() 函数。
大多数时候null更好。可能在某些情况下它几乎没有什么区别,但它们很少。请记住,当您查询field = ''
与field is null
(至少在 MySQL 中)不同时。
据我所知,甲骨文没有区别。
select 1 from (select '' as col from dual) where col is null;
考虑一下为什么列中没有数据。这是否意味着桌子设计马虎?尽管不喜欢空值,但有时它们是合适的(或足够合适的),并且系统通常不会死机。只是永远不允许在任何候选键(主键或备用键)中出现空值。
仅为可空列和主表的外键创建一个单独的表。如果一条记录没有该列的数据,那么它在第二个表中将没有记录。这是最干净的解决方案,您不必担心处理空值或为空字符串赋予特殊含义。
NULL 是一个非值,应该归入它出现的黑暗时代。我发现处理特殊的 NULL 情况需要大量的编程,这些情况可以很容易地用默认值处理。
将列的默认值设置为空字符串。强制列不允许 null,一旦您分配了默认值,这很可能永远不会发生。愉快地编写代码,忽略列值为空的情况。
对于 NULL,我一直遇到的一个大问题是“SELECT * from tbl WHERE column = NULL”将始终返回一个空的结果集。NULL 永远不能等于任何东西,包括 NULL。特殊关键字“column is null”是检查是否为 null 的唯一方法。如果你远离null,那么比较就会成功:“column = ''”返回7行。
我从头开始完成了两个主要的数据库实现,最后我后悔使用 NULL。下一次,我没有空值!
有一个重要的例外。Bill Karwin 说“CONCAT(NULL, 'foo') 产生 NULL”这对于大多数 RDBMS 来说是正确的,但对于 Oracle 则不然。
正如上面 James Curran 所建议的那样,Oracle 选择了这个相当关键的时刻,通过对 NULL 和空字符串的处理完全相同来脱离标准 SQL。然而,更糟糕的是,它实际上可以通过在连接时返回 NULL 以外的值来破坏 NULL 值的含义。
具体来说,在 oracle 中 CONCAT(NULL, 'foo') 产生 'foo'。感谢 Oracle,我现在丢失了我的空值,这对你来说可能无关紧要,但当数据传递到其他 RDBMS 进行进一步处理时,肯定会有所不同。
列中的“无数据”值应由默认值表示。请记住,NULL 表示未知值,即该列可以有值或没有值,但此时您还不知道。
例如,在贷款申请系统中,驾驶执照号码字段上的 NULL 值表示申请人或贷款处理人没有输入驾驶执照号码。NULL 值并不自动意味着申请人没有许可证。他可能有也可能没有执照,你只是不知道,这就是为什么它是 NULL。
歧义在于字符串列。如果没有值,数字列显然包含零。你怎么能表示一个没有值的字符串?在上面的示例中,对于没有驾驶执照的申请人,您可以分配任意默认值,例如“none”或更好的空字符串。只需确保您在其他表中使用默认的空值以保持一致性。
关于不使用 NULL 作为原则的问题,在某些情况下它们实际上是必不可少的。作为广泛使用统计数据的人,数据提供者通常会为您提供数据不完整的数据集。例如,在每个国家的 GDP 数据集中,您可以找到早年和晚年缺失的 GDP 数据。原因之一是该国政府没有这些年的官方数据。断定他们的 GDP 为零(DUH!)并在提取的数据或图表中显示零值是不正确的。正确的值为 NULL,这意味着您还没有数据。最终用户将提取的数据和图表中缺失的数据点正确解释为非零。此外,它不会导致计算错误,尤其是在进行平均时。
在您的情况下,一些理论上有意义的“规则”实际上是一个糟糕或不正确的解决方案。
我发现 NULL 值有助于参照完整性。在 MySQL 的情况下,如果字段设置为 NOT NULL,则插入需要设置数据;否则,NULL 是一个可能的值,并且不强制执行外键约束。
- id:主键
- product_id:外键不为空
- ref_id: (NULLABLE)
id 和 product_id 区域始终需要。ref_id 可以设置为 NULL。但是,如果使用任何其他值,它必须满足 FOREIGN KEY 约束。