这两个SELECT语句是否相同?奇怪的使用ISNULL

时间:2015-07-01 19:21:54

标签: sql sql-server

我熟悉SQL Server中的ISNULL函数,但从未以这种方式使用它。我在db I支持中遇到了这段代码:

>>> next((j,k) for i,j,k in L if i=='John')
(1234, 'California')

在我看来,这与

相同
Select * from employee where deptId = 58 and gender = ISNULL('M', gender)

我尝试使用null来查看2个语句是否会返回不同的结果,但它们始终是相同的。有没有人知道第一个选择是否优先于第二个选择是否有任何好处或场景?我正在使用SQL 2014.也许这种语法在以前的版本中很有用?

由于

1 个答案:

答案 0 :(得分:4)

这些陈述,它们的确切方式是相同的。

使用gender = ISNULL('M', gender)gender = 'M'

没有区别 在这种情况下,

ISNULL可能有意义:

DECLARE  @gender CHAR(1)

SELECT  *
FROM    employee
WHERE   deptId = 58
        AND gender = ISNULL(@gender, gender)

,如果@gender设置为NULL,则返回所有非空性别行,否则返回给定性别的行。

如果您正在使用此语句,请确保在每次调用时重新编译它,因为NULL的计划和非空值可能会完全不同。

这可以通过创建样本表来轻松测试:

CREATE TABLE test (id INT NOT NULL PRIMARY KEY)
GO

;
WITH    q AS
        (
        SELECT  1 id
        UNION ALL
        SELECT  id + 1
        FROM    q
        WHERE   id <= 100000
        )
INSERT
INTO    test
SELECT  id
FROM    q
OPTION  (MAXRECURSION 0)
GO

然后启用两个批次并启用实际执行计划:

SET STATISTICS IO ON
SET NOCOUNT ON
GO

DECLARE @id INT = 7

SELECT  *
FROM    test
WHERE   id = ISNULL(@id, id)
GO

DECLARE @id INT = 7

SELECT  *
FROM    test
WHERE   id = ISNULL(@id, id)
OPTION  (RECOMPILE)
GO

并研究计划和统计数据:

Table 'test'. Scan count 1, logical reads 337, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'test'. Scan count 0, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.