我今天正在编写一个简单的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的接近金属实现细节,或语言的哲学差异?)
答案 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 NULL
和IS 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对此有很好的解读。
<强> - 编辑 - 强>
要回答您的评论,请与NULL
和ZERO
进行比较。
零是一个值。它是唯一的,已知的零数量,在算术/数学中有意义地使用。我们可以做零事。
另一方面,Null是一个非值,它只是一个未知或未指定的数据值的占位符。数学不能在NULL上执行。未定义是NULL的另一个术语。 NULL不存在,所以我们无法对它做任何事情。 Null不为零,null不是&#34;&#34; (空字符串)。 Null只是一个未知数据的表示。
我希望它现在清楚了。 :)
答案 4 :(得分:1)
在SQL中,NULL不等于其他NULL。
如果我没有告诉你我的年龄,而你没有告诉我你的年龄,那么我们的年龄是否相同?
不,我们不能说这是一个真正的谓词。我们根本没有足够的信息来说明这种或那种方式。它不完全是假的,但它也不一定是正确的。
SQL中的column_name = NULL
和column_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')
可能会很方便,但这不是语言标准定义的方式,无论好坏。