MySQL:为什么我不能“column_name不在(null,'foo')”?

时间:2014-04-11 18:09:01

标签: mysql sql

我今天正在编写一个简单的MySQL查询:

SELECT * FROM table_name WHERE column_name IS NOT NULL and column_name !='foo';

这返回了预期的结果数。但我并不喜欢这种语法,并试图让它更优雅:

SELECT * FROM table_name WHERE column_name NOT IN (NULL, 'foo');

当然,返回0结果。

我的问题是:你能解释为什么空值不在(NULL, 'bar')吗?我认为这是因为你无法比较{{1与NULL,至少在哲学上。但为什么不呢?

考虑一下:

NULL

在这些语言中,nil或undefined值等于任何其他nil或undefined值。为什么不在SQL?

(关于SQL的接近金属实现细节,或语言的哲学差异?)

5 个答案:

答案 0 :(得分:2)

在SQL中,与NULL的直接比较既不是真也不是假,因此IN子句不起作用。这是ISO SQL标准的基本特征 1

请参阅此Wikipedia条目:

  

由于Null不是任何数据域的成员,因此它不被视为“值”,而是指示缺少值的标记(或占位符)。因此,与Null的比较永远不会导致True或False,但总是在第三个逻辑结果中,Unknown。

通过这种方式,SQL中的NULL概念与Ruby的nil或JavaScript的undefined非常不同。 Ruby的nil是'值',因此nil == nil true 。但是,SQL的NULL不是'值',因此NULL = NULL 未知(但NULL <> NULL也是如此)。出于这个原因,SQL为比较NULL提供了不同的运算符 - NULL IS NULL true

1:有些人可能不同意这实际上是一个特征。

答案 1 :(得分:1)

  

你能解释为什么空值不在(NULL, 'bar')

Necause SQL NULL 等于其他NULL。这就是定义SQL NULL的方式,因为该语言使用三值逻辑(3VL) * 。从本质上讲,NULL意味着“未知”,因此所有与它的比较都会导致未知结果 - 即NULL。例如,column_name = NULL的结果是NULL,而不是false。这就是将IS NULLIS NOT NULL运算符引入SQL语言背后的原因。

您的第一个解决方案是正确的。您还可以使用不太直接的解决方案,在比较之前将NULL转换为'foo',但此转换产生的表达式需要更多的思考才能理解:

WHERE IFNULL(column_name, 'foo') != 'foo'

* SQL中NULL的行为,尤其是聚合期间处理它们的方式之间的差异,一直是争议的主题。关于如何“修复”这种行为提出了一些建议,但由于它们的复杂性,它们都没有被广泛采用。

答案 2 :(得分:1)

数据库结构查询语言SQL实现三值逻辑作为处理与NULL字段内容进行比较的方法。

True
False
Unknown

SQL中NULL的原始意图是表示数据库中缺少的数据,即假设存在实际值,但该值当前未记录在数据库中。

因此,与UNKNOWN值的比较给出了不确定的结果,这被认为是假的。

答案 3 :(得分:1)

IN Clause期望一个值,NULL不是值。因此,您必须将OR与null一起使用才能获得所需的结果。

MySQL manual对此有很好的解读。

<强> - 编辑 -

要回答您的评论,请与NULLZERO进行比较。

零是一个值。它是唯一的,已知的零数量,在算术/数学中有意义地使用。我们可以做零事。

另一方面,Null是一个非值,它只是一个未知或未指定的数据值的占位符。数学不能在NULL上执行。未定义是NULL的另一个术语。 NULL不存在,所以我们无法对它做任何事情。 Null不为零,null不是&#34;&#34; (空字符串)。 Null只是一个未知数据的表示。

我希望它现在清楚了。 :)

答案 4 :(得分:1)

在SQL中,NULL不等于其他NULL。

如果我没有告诉你我的年龄,而你没有告诉我你的年龄,那么我们的年龄是否相同?

不,我们不能说这是一个真正的谓词。我们根本没有足够的信息来说明这种或那种方式。它不完全是假的,但它也不一定是正确的。

SQL中的column_name = NULLcolumn_name != NULL都是UNKNOWN,只有满足它们的条件才会满足条件。

column_name IN (NULL, 'foo')在逻辑上与(column_name = NULL) OR (column_name = 'foo')相同。

同样,column_name NOT IN (NULL, 'foo')在逻辑上与NOT ((column_name = NULL) OR (column_name = 'foo'))(column_name != NULL) AND (column_name != 'foo')相同。

无论哪种方式,都适用与NULL比较相同的规则。

如果SQL自动将其转换为(column_name IS NULL) OR (column_name = 'foo')可能会很方便,但这不是语言标准定义的方式,无论好坏。