七星揽月

Efforts To Make The Best Of Their……
一口吃不出一个胖子,但胖子却是一口一口吃出来的,只要能每天坚持下来,我相信,一定会有收获的
每天进步一点点
  博客园  :: 首页  :: 新随笔  :: 联系 :: 管理

    我在做一个需求是这样的:联查多张表,并且更据条件返回数据。

    但是,根据我的WHERE条件获取到的数据总是不正确,通过反复的研究,发现了问题的所在:

    某些列的值为NULL,在把这些列作为条件时,就会匹配不到正确的值,故而返回不正确的数据。

    示例:

    数据表(Users)及数据如下:

   image

    需求:查询所有数据中,Name不是以’L’开头并且Mobile中不包含’186’ 的数据   

    SQL语句:

SELECT 
	* 
FROM 
	dbo.Users 
WHERE 
	[Name] NOT LIKE 'L%' AND 
	Mobile NOT LIKE '%186%'

 


    查询结果如下:

    image

 

  奇怪,为什么获取不到数据呢?实际应该返回ID等于4和5的数据才对的。

   image

于是,我思考了起来。。。。。。。。。思考中。。。。。。。。。

 

突然,眼前一亮,请注意:数据列中为NULL的地方 , 是的,没错问题就处在这里。

那么什么是NULL值呢???

NULL表示值为空,为空就是说该字段还没有经行任何的赋值操作,它的值是未知的,所以我们无法拿它与其他类型的值经行比较,如果用它去和其他值比较的话,那么返回的一定是未知,这样,我们得到的数据就是不准确的数据了。

 

 

 

 

说道NULL值,就一定得说一下什么是三值逻辑,在SQL中有逻辑运算和比较运算,他们的取值一般有两种:True和False ,但是在表达式中涉及到NULL值的时候,取值就会是第三种,即UNKNOWN

关于UNKNOWN的相关知识点整理如下:
1、NOT  TRUE 等于 FALSE,,NOT  FALSE 等于 TRUE,,否定的UNKNOWN还是UNKNOWN;
2、比较两个NULL值,将返回FALSE而不是UNKOWN;
3、所有的查询筛选器(ON、WHERE和HAVING)都会把UNKNOWN当作FALSE处理,UNKNOWN的行会被排除在结果集之外;
4、CHECK约束中的UNKNOWN被当作TRUE来处理,假设表中包含一个CHECK约束,要求salary列的值必须大于0,向该表插入salary为NULL的行时可以被接受;
5、如果表中有一列定义了UNIQUE约束,将无法向表中插入两行该列值为NULL的数据;
6、GROUP BY会把所有NULL值分组到一起;ORDER BY 会把所有的NULL值排列在一起;
7、NULL值在聚合函数里的使用有点意思:Count(*)会返回表中的所有行,Count(salary)将会排除掉salary为NULL的行;
     使用AVG(salary)求平均值时也会排除掉salary为NULL的行,这样可能会导致计算的平均值不准确,需要将NULL转换成0或其它默认值再参与计算;
     在数据库设计时,关键字段上应考虑设计默认值,防止在统计时出现误差;

(摘自:http://www.cnblogs.com/Yuanet/archive/2011/03/17/1986808.html ,我是看了这些才学习到三值逻辑的 :) )

好了,先说到这儿,继续处理需求,怎么避免NULL值呢???

很简单,既然NULL值无法和其他值进行比较,那么,我们就先对它进行转换,让它和要比较的值类型一致,这样就可以了。这里,我们使用ISNULL函数来完成转换。

先说一下ISNULL函数的语法

ISNULL ( check_expression , replacement_value )
check_expression
:将被检查是否为 NULL 的表达式。 check_expression 可以为任何类型。
replacement_value:当 check_expression 为 NULL 时要返回的表达式。 replacement_value 必须是可以隐式转换为 check_expresssion 类型的类型。

ISNULL函数的返回类型:如果文字 NULL 作为 check_expression 提供,则返回 replacement_value 的数据类型。 如果文字 NULL 作为 check_expression 提供并且未提供 replacement_value,则返回 int。

(具体ISNULL的相关信息,参见MSDN:http://msdn.microsoft.com/zh-cn/library/ms184325.aspx)

 

好了,来看看用ISNULL处理过的T-SQL语句吧:

SELECT 
	* 
FROM 
	dbo.Users 
WHERE 
	ISNULL([Name],'') NOT LIKE 'L%' AND 
	ISNULL(Mobile,'') NOT LIKE '%186%'

 

 

执行结果如下:

image

 

OK,这回,得到了我们想要的结果,问题解决了。