SQL Server:Null VS 空字符串

92

SQL Server 中,NULL 和空的 Varchar 值是如何存储的?如果我在我的 UI 上没有用户输入一个 string 字段,我应该存储一个 NULL 还是 ''


相关内容:SQL:空字符串 vs NULL 值 - Edward Brey
如果您选择使用空字符串,请确保它是空的!去掉任何空格!必要时进行两次修剪以确保其为空!拜托了。 - Airn5475
9个回答

82
有一篇不错的文章在这里讨论了这个问题。需要记住的关键点是,表大小没有区别,但有些用户更喜欢使用空字符串,因为这样可以使查询更容易,因为不需要进行NULL检查。只需检查字符串是否为空即可。还要注意的一件事是,在关系数据库的上下文中,NULL的含义。它意味着行头中的指向字符字段的指针被设置为0x00,因此无法访问数据。

更新 这里有一篇详细的文章,谈论了每行基础上实际发生的情况

每行都有一个允许空值的列的null位图。如果该列中的行为空,则位图中的一个位为1,否则为0。

对于可变大小的数据类型,实际大小为0字节。

对于固定大小的数据类型,实际大小为默认数据类型大小(数字为0,字符为'')的字节数。

DBCC PAGE的结果显示,NULL和空字符串都占用零字节


2
这并不是对问题的讨论,只是某人表达了他们的观点,没有任何支持。他们提出的唯一观点是空间要求相同,这并不支持任何一种方法。 - MikeKulls
13
另一个需要注意的是,在关系数据库的上下文中,NULL的含义是什么。这意味着在行头中,指向字符字段的指针被设置为0x00,因此无法访问任何数据。然而,在关系数据库的上下文中,NULL并不总是具有这个含义,它只在某些特定供应商的关系数据库实现中才有这个含义。 - Thanatos
7
第一个链接已失效。 - Spivonious
1
@Spivonious - 链接现已修复。 - openshac
我不同意第一篇文章的前提,即使用“”而不是NULL更好。在SELECT查询中,NULL显示为NULL,而“”显示为<<nothing>>。我宁愿看到“something”而不是“nothing”,以确保它是一个NULL。 - Fandango68
显示剩余2条评论

53

在 SQL Server 中,小心处理 null 值并检查不等式。

例如:

select * from foo where bla <> 'something' 

将不会返回bla为null的记录,虽然从逻辑上讲应该会返回。

因此正确的检查方式是

select * from foo where isnull(bla,'') <> 'something' 

当然,人们经常会忘记这一点,然后出现奇怪的错误。


11
要接受“null = null”返回false已经够难了,但是“null <> 'something'”也返回false,这实在是太残忍了。 - MikeTeeVee
17
无论哪种情况,它都不是“FALSE”,而是“UNKNOWN”,并且不满足条件(只有“TRUE”结果才能通过)。 - ypercubeᵀᴹ
3
上面的查询可以进行一些优化,这样它会更快一些。你可以使用 select * from foo where (bla <> 'something') or (bla is null) 代替 select * from foo where isnull(bla,'') <> 'something' - Nicolas
但是这个条件会使空字符串和NULL相同。 - Jimmy T.

20

在数据库设计中,“NULL”和“空字符串”之间的概念差异是真实且非常重要的,但往往被误解和不当应用——以下是两者的简短描述:

NULL - 意味着我们不知道该值是什么,它可能存在,也可能不存在,我们只是不知道。

空字符串 - 意味着我们知道该值是什么,即为空。

这里有一个简单的例子: 假设您有一张包含人名的表格,其中包括first_namemiddle_namelast_name三个独立列。在first_name = 'John',last_name = 'Doe',而middle_name为NULL的情况下,这意味着我们不知道中间名是什么,或者它是否存在。将该场景更改为middle_name = ''(即空字符串),现在意味着我们知道没有中间名。

我曾听说过一个SQL Server教练提倡使数据库中的每个字符类型列都是必需的,并分配每个列的默认值为''(空字符串)或'unknown'。通过这种说法,该教练表明他对NULL和空字符串之间的差异没有清晰的理解。不可否认,这些差异可能令人困惑,但对我来说,上面的例子有助于澄清差异。此外,在编写SQL代码时正确处理NULL和空字符串也很重要。


14
我想指出这并不是普遍客观的观点。 - industryworker3595112
3
你在这里主张NULL表示“未知”,而不应该表示“无”/“不适用”。但是其他数据类型呢?如果我们有一个名为CONTRACTS的表,其中包含类型为DATE的“maturity_date”列。如果我们有一份合同没有到期日(例如存款直到要求),在这种情况下,处理它的一种相当被接受的方式是将“maturity_date=NULL”留空。(即对于其他任何数据类型,“无”/“不适用”情况下使用NULL是合适的)(我的观点:null vs empty-string vs special-value只是一种约定惯例的问题) - industryworker3595112
是的,我必须同意这更像是两者中的一种单一实现。这是合理的,但其他实现也是如此。 - Mike M

17

空字符串是长度为零或没有字符的字符串。 null表示缺少数据。


4
这是关于NULL的一种解释。在某些情况下,它显然是正确的。但是,在SQL中,当涉及到NULL时并不一致,因此有一些情境下NULL的意思是未知的。例如,“NULL != 'x'”返回NULL,因为在这种情境下,NULL表示未知。如果它是一个缺席值,那么这样的比较就没有意义,因为'x'并不等同于一个缺席值。 - Federico Razzoli
为什么我们要比较 NULL 和 '' 的空间占用?谁在乎呢!?NULL 表示没有数据,而 '' 表示一个零长度的字符串。 - Fandango68
2
@Fandango68 对于存储优化:我们中的一些人拥有数十亿行的表,如果某个特定表示(NULL''N'' 中的一个)使用的磁盘空间较少或处理速度更快,而不会以其他方式损害我们的数据库设计,则可以节省大量运营费用。 - Dai
@Dai 哇,每天都能学到新东西。谢谢。 - Fandango68

3

所有列中的NULL值都会被单独存储在特殊的位图空间中。

如果您的应用程序不区分NULL'',那么我建议您在表中存储''(除非字符串列是外键,在这种情况下,如果与应用程序逻辑兼容,则最好禁止该列存储空字符串并允许NULL)。


1

如果不是外键字段,不使用空字符串可能会为你带来一些麻烦。只有当null代表的含义与空字符串不同才允许使用null。例如,如果您有一个密码字段,null值可以表示新用户尚未创建密码,而空varchar可以表示空密码。对于"地址2"这样的字段,允许null只会使事情变得更加困难。需要注意的事项包括Vagif Verdi提到的null引用和=以及<>操作符产生的意外结果,而关注这些事情通常是程序员不必要的开销。

编辑:如果性能是一个问题,请参考这个相关的问题:可为空与非空varchar数据类型-哪个查询速度更快?


1

NULL 是一个非值,就像未定义一样。 '' 是一个没有字符的空字符串。
数据库中字符串的值取决于您在 UI 中的值,但通常情况下,如果您在查询或存储过程中指定了参数,则为空字符串''


0

就判断VARCHAR列中的值是否为空,我写了一个函数来帮我做决定。

CREATE FUNCTION [dbo].[ISNULLEMPTY](@X VARCHAR(MAX))
RETURNS BIT AS
BEGIN
    DECLARE @result AS BIT
    IF @X IS NOT NULL AND LEN(@X) > 0
        SET @result = 0
    ELSE
        SET @result = 1
        
    RETURN @result
END

现在毫无疑问。


-2
在SQL Server中,"NULL"和"空字符串"值是如何存储的呢?你为什么想知道这个呢?换句话说,如果你知道答案,你会如何使用这个信息呢?
而且,如果我的用户界面上没有一个字符串字段的输入,我应该存储NULL还是''(空字符串)呢? 这取决于字段的性质。问问自己,空字符串是否是该字段的有效值。
如果是(例如,地址中的房屋名称),那么根据你是否知道该地址没有房屋名称,这可能是你想要存储的内容。
如果不是(例如,一个人的名字),那么你应该存储一个null,因为人们没有空白姓名(据我所知,在任何文化中都是如此)。

1
我知道这并不是很重要,但我还是想得到它。 - Akram Shahda

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接