我知道COALESCE
可以传递多个参数,但是当你只想检查一个表达式是否存在时,是使用默认值还是最好使用ISNULL
呢?
这两者之间是否有性能上的差异?
这个在Microsoft Connect上报告的问题揭示了COALESCE
和ISNULL
之间的一些差异:
我们处理的一个早期部分将
COALESCE(expression1, expression2)
重写为CASE WHEN expression1 IS NOT NULL THEN expression1 ELSE expression2 END
。 在[此示例]中:
COALESCE ( ( SELECT Nullable FROM Demo WHERE SomeCol = 1 ), 1 )
我们生成:
SELECT CASE WHEN (SELECT Nullable FROM Demo WHERE SomeCol = 1) IS NOT NULL THEN (SELECT Nullable FROM Demo WHERE SomeCol = 1) ELSE 1 END
查询处理的后续阶段不知道这两个子查询最初是相同的表达式,因此会执行两次子查询...
一种解决方法,虽然我不太想建议这样做,是将
COALESCE
更改为ISNULL
,因为后者不会重复执行子查询。
我认为不行,但COALESCE是SQL '92标准中支持的,并且被更多不同的数据库所支持。如果你想要可移植性,不要使用ISNULL。
ifnull
,SQL Server 使用 isnull
。 - nawfalCOALESCE
替代方案是NVL
。因此,即使在数据库中实现细节不同,COALESCE作为标准的观点仍然是有效的。 - Suncat2000我看不到明确表述的一件重要事情是,ISNULL
的输出类型与第一个表达式类似,但使用 COALESCE
,它返回具有最高优先级值的数据类型。
DECLARE @X VARCHAR(3) = NULL
DECLARE @Y VARCHAR(10) = '123456789'
/* The datatype returned is similar to X, or the first expression*/
SELECT ISNULL(@X, @Y) ---> Output is '123'
/* The datatype returned is similar to Y, or to the value of highest precedence*/
SELECT COALESCE(@X, @Y) ---> Output is '123456789'
select * from SomeTable
where IsNull(SomeNullableBitField, -1) != IsNull(SomeOtherNullableBitField, -1);
这与之不同
select * from SomeTable
where coalesce(SomeNullableBitField, -1) != coalesce(SomeOtherNullableBitField, -1);
因为在第一种情况下,IsNull() 函数会强制类型为 bit(所以 -1 被转换为 true),而第二种情况将两个值都提升为 int。
with input as
(
select convert(bit, 1) as BitOn,
convert(bit, 0) as BitOff,
convert(bit, null) as BitNull
)
select BitOn,
BitOff,
BitNull,
IsNull(BitOn, -1) IsNullBitOn, -- true
IsNull(BitOff, -1) IsNullBitOff, -- false
IsNull(BitNull, -1) IsNullBitNull, -- true, converts the -1 to bit
coalesce(BitOn, -1) CoalesceBitOn, -- 1
coalesce(BitOff, -1) CoalesceBitOff, -- 0
coalesce(BitNull, -1) CoalesceBitNull -- -1
from input;
问题本身有一个类似的评论/链接(@Martin Smith)。
NULL
和COALESCE
并不总是可以互换的。了解它们的区别很重要,以便在何时更好地使用其中之一:上面这张表格是来自Itzik Ben-Gan的书《Exam Ref 70-761 Querying Data with Transact-SQL》中的ISNULL
和COALESCE
的比较。
2
for ISNULL
vs >2
when using COALESCE
ISNULL
is proprietary T-SQL feature and COALESCE
is ISO/ANSI SQL standardThe data type of the result is important. After reading notes in the table above, check the following cases:
DECLARE @x VARCHAR(3) = NULL
,@y VARCHAR(10) = '1234567890';
SELECT ISNULL(@x, @y) AS [ISNULL], COALESCE(@x, @y) AS [COALESCE];
The ISNULL
is getting the data type of the first argument as it is the not
NULL
literal. It is VARCHAR(3)
and is a result, the second argument data
is cut to match it. With COALESCE
the data type if highest precedence is
used.
DECLARE @x VARCHAR(8) = '123x5'
,@y INT = 123;
SELECT ISNULL(@x, @y) AS [ISNULL];
SELECT COALESCE(@x, @y) AS [COALESCE];
The ISNULL
is returning the data type of first argument, while in
COALESCE
we are getting error, as the INT
has highest precedence and the
conversion of the first argument value to INT
fails.
The nullability of the result can be important, too. For, example:
DECLARE @x VARCHAR(3) = NULL
,@y VARCHAR(3) = NULL;
DROP TABLE IF EXISTS [dbo].[DataSource01];
SELECT ISNULL(10, 20) AS [C1]
,ISNULL(@x, 'text') AS [C2]
,ISNULL(@x, @y) AS [C3]
INTO [dbo].[DataSource01];
DROP TABLE IF EXISTS [dbo].[DataSource02];
SELECT COALESCE(10, 20) AS [C1]
,COALESCE(@x, 'text') AS [C2]
,COALESCE(@x, @y) AS [C3]
INTO [dbo].[DataSource02];
Let's check the Nullable
property of each column:
Using COALESCE
we have a NOT NULL
property of column set to Yes
, only
when all of the inputs are non null-able.
According to the SQL standard, the COALESCE
expression is translated to:
CASE WHEN (<subquery>) IS NOT NULL THEN (<subquery>) ELSE 0 END
If the result of the execution of the subquery in the WHEN clause isn’t NULL, SQL Server executes it a second time in the THEN clause. In other words, in such a case it executes it twice. Only if the result of the execution in the WHEN clause is NULL, SQL Server doesn’t execute the subquery again, rather returns the ELSE expression. So when using subqueries, the ISNULL function has a performance advantage.
COALESCE ("expression 1", "expressions 2", ...)
它与以下CASE语句相同:
SELECT CASE ("column_name")
WHEN "expression 1 is not NULL" THEN "expression 1"
WHEN "expression 2 is not NULL" THEN "expression 2"
...
[ELSE "NULL"]
END
FROM "table_name";
在SQL Server中,ISNULL()函数用于将NULL值替换为另一个值。
select CountryName = ISNULL("columnname", 'INDIA') from Countries
COALESCE函数返回第一个非空表达式,而isnull()函数用于将null值替换为我们期望的值。
COALESCE是ANSI标准的一部分,几乎所有数据库都支持它。
在选择ISNULL和COALESCE之间时,必须注意以下参数:
Consider following sql statements
DECLARE @c5 VARCHAR(5);
SELECT 'COALESCE', COALESCE(@c5, 'longer name')
UNION ALL
SELECT 'ISNULL', ISNULL(@c5, 'longer name');
结果:
COALESCE longer name
ISNULL longe
如果只有一个空值条件,ISNULL
的开销会更小。尽管差别可能微不足道。
DECLARE @Value1 INT, @Value2 INT, @Value3 INT, @Value4 INT
SELECT @Value2 = 2, @Value4 = 4
SELECT COALESCE(@Value1, @Value2, @Value3, @Value4)
SELECT COALESCE(@Value1, @Value4, @Value3, @Value2)
在 ISNULL 中,如果表达式为 null,则返回提供的第二个参数,当然你只能检查一个表达式...
因此,如果想要检查多个表达式并选择其中第一个非空值,则使用 COALESCE,否则使用 ISNULL。
ISNULL
函数将结果强制转换为第一个表达式的数据类型,具体演示见这里。 - Martin Smith