Sql中的空检查

Sql中的空检查,sql,sql-server,Sql,Sql Server,请说明以下两者之间的区别: 1) 其中student.name=ISNULL(@name,student.name) 及 2) 其中(student.name=@name或@name为空) 实际上,我有一个针对我名字的问题bug,当我使用第一个方法时,一些记录被跳过了。但是在我用eg 2替换它时得到了更正。如果系统设置为其他设置,null=anything为false 因此,第一个查询不会返回student.name为null的任何条目,即使@name为null,因为对于student.name

请说明以下两者之间的区别:

1)
其中student.name=ISNULL(@name,student.name)

2)
其中(student.name=@name或@name为空)

实际上,我有一个针对我名字的问题bug,当我使用第一个方法时,一些记录被跳过了。但是在我用eg 2替换它时得到了更正。

如果系统设置为其他设置,
null=anything
为false

因此,第一个查询不会返回
student.name
为null的任何条目,即使
@name
为null,因为对于student.name为null的条目,比较结果为
其中null=null
,而
null=null
返回false

第二条语句说,当学生名与@name匹配时选择记录,或者当没有指定姓名时,如果指定了@name,则为该姓名选择记录。如果@name为空,请选择所有记录。这与@name为NULL时表中的值无关

对于第一条语句,如果@name为NULL,它将使用与当前行的student.name相同的student.name

当@name和student.name都为空时

WHERE student.name = @name OR @name IS NULL -- the other part of the OR is true so records will be returned

由于
NULL=NULL
返回false,因此不会返回该行的任何记录for
ISNULL()
是替换值,这意味着如果第一个参数为NULL,将替换该值。因此,如果
@name
student.name
都是
null
,那么您基本上是在写:

student.name=NULL

它等于false(因为SQL中的
null
被认为是未知的,并且永远不等于任何东西)

在第二个示例中,您使用
IS
操作符测试空值,如果
@name
为空,则返回
true

WHERE student.name = ISNULL(@name, student.name)

除非student.name为null,否则为等效

WHERE (student.name = @name OR @name IS NULL)
可简化为:

WHERE COALESCE(student.name,'nul') = COALESCE(@name, student.name,'nul')

相当于

WHERE (student.name = @name OR @name IS NULL AND student.name IS NOT NULL)
这就是区别

name |student.name  |first_result  |second_result |expected*
A    |A             |true          |true          |true
A    |B             |false         |false         |false
null |A             |true          |true          |true
A    |null          |false         |false         |false
null |null          |FALSE         |TRUE          |TRUE
*预期-某些人预期,但在我们的宇宙中并不正确

如您所见,当两个值都为NULL时,就会出现差异,因为在这种情况下,第一个WHERE的计算结果为: null=null(这是FALSE)

您可以在SQL Server中通过以下方式检查:

select case when null = null then 1 else 0 end

这将为您提供0。

检查下面的示例,在第二个选项中,您可以在检查name=@name之前检查@name是否为null

declare @name varchar(10) = null
declare @table table (name varchar(10))

insert into @table 
select 'A'
UNION
SELECT null


---returns only A because null = column is always false
select * from @table where name = ISNULL(@name, name)

--returns all rows
select * from @table where (@name is null or name = @name)


set @name = 'A'
select * from @table where name = ISNULL(@name, name)
select * from @table where (@name is null or name = @name)

如果
@name
不为空,则第一个语句没有区别,如果两者都为空,则为NULL=NULL,这意味着当@name为空时,第一个查询将仅在student.name不为null时返回,第二个查询将返回所有行。正确,如果您传入的
@name
为null,则第一个查询将返回任何非null student(例如
'bob'='bob'
),其中与第二个查询一样,将返回所有内容,因为
@name为null,所以所有行的
都为true。是的,这是一个相当奇怪的问题。哇,太棒了……这真的消除了我的疑虑。这里主要强调的一点是Mike所说的“因为SQL中的null被认为是未知的,并且永远不等于任何东西”。就连我也觉得NULL==NULL返回True,但实际上它是FALSE。
name |student.name  |first_result  |second_result |expected*
A    |A             |true          |true          |true
A    |B             |false         |false         |false
null |A             |true          |true          |true
A    |null          |false         |false         |false
null |null          |FALSE         |TRUE          |TRUE
select case when null = null then 1 else 0 end
declare @name varchar(10) = null
declare @table table (name varchar(10))

insert into @table 
select 'A'
UNION
SELECT null


---returns only A because null = column is always false
select * from @table where name = ISNULL(@name, name)

--returns all rows
select * from @table where (@name is null or name = @name)


set @name = 'A'
select * from @table where name = ISNULL(@name, name)
select * from @table where (@name is null or name = @name)