技术开发 频道

与你预想的不一样的MySQL的10件事

    【IT168 技术文档】 #10. 搜索一个“NULL”值

SELECT  *
FROM    a
WHERE   a.column
= NULL


  在SQL中,NULL什么也不等于,而且NULL也不等于NULL。这个查询不会返回任何结果的,实际上,当构建那个plan的时候,优化器会把这样的语句优化掉。

  当搜索NULL值的时候,应该使用这样的查询:

SELECT  *  
FROM    a  
WHERE   a.column
IS NULL

 

  #9. 使用附加条件的LEFT JOIN

SELECT  *  
FROM    a  
LEFT JOIN        
        b  
ON      b.a = a.id  
WHERE   b.column
= 'something'

 

  除了从a返回每个记录(至少一次),当没有真正匹配的记录的时候,用NULL值代替缺失的字段之外,LEFT JOIN和INNER JOIN都是一样的。

  但是,在LEFT JOIN之后才会检查WHERE条件,所以,上面这个查询在连接之后才会检查column。就像我们刚才了解到的那样,非NULL值才可以满足相等条件,所以,在a的记录中,那些在b中没有对应的条目的记录不可避免地要被过滤掉。

  从本质上来说,这个查询是一个INNER JOIN,只是效率要低一些。

  为了真正地匹配满足b.column = 'something'条件的记录(这时要返回a中的全部记录,也就是说,不过滤掉那些在b中没有对应的条目的记录),这个条件应该放在ON子句中:

SELECT  *  
FROM    a  
LEFT JOIN    
        b  
ON      b.a = a.id        
        
AND b.column = 'something'

 

  #8. 小于一个值,但是不为NULL

  我经常看到这样的查询:

SELECT  *  
FROM    b  
WHERE   b.column
< 'something'        
        AND b.column IS NOT NULL

 

  实际上,这并不是一个错误:这个查询是有效的,是故意这样做的。但是,这里的IS NOT NULL是冗余的。

  如果b.column是NULL,那么无法满足b.column < 'something'这个条件,因为任何一个和NULL进行的比较都会被判定为布尔NULL,是不会通过过滤器的。

  有趣的是,这个附加的NULL检查不能和“大于”查询(例如:b.column > 'something')一起使用。

  这是因为,在MySQL中,在ORDER BY的时候,NULL会排在前面,因此,一些人错误地认为NULL比任何其他的值都要小。

  这个查询可以被简化:

SELECT  *  
FROM    b  
WHERE   b.column
< 'something'

 

  在b.column中,不可能返回NULL

  #7. 按照NULL来进行连接

SELECT  *  
FROM    a  
JOIN    b  
ON      a.column = b.column

 

  在两个表中,当column是nullable的时候,这个查询不会返回两个字段都是NULL的记录,原因如上所述:两个NULL并不相等。

  这个查询应该这样来写:

SELECT  *  
FROM    a  
JOIN    b  
ON      a.column = b.column        
        
OR (a.column IS NULL AND b.column IS NULL)

 

  MySQL的优化器会把这个查询当成一个“等值连接”,然后提供一个特殊的连接条件:ref_or_null 

0
相关文章