我知道可以将多个参数传递给COALESCE
,但是当您只想检查一个表达式以查看它是否不存在时,您使用默认值还是使用更好的做法ISNULL
?
两者之间是否有任何性能提升?
我知道可以将多个参数传递给COALESCE
,但是当您只想检查一个表达式以查看它是否不存在时,您使用默认值还是使用更好的做法ISNULL
?
两者之间是否有任何性能提升?
ISNULL
还将结果强制为第一个表达式的数据类型,如下所示
Answers:
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中,您可以有多个表达式,而在ISNULL中,您只能检查一个表达式
COALESCE ( expression [ ,...n ] )
ISNULL ( check_expression , replacement_value )
值得一提的是,两者之间的类型处理也可以有所作为(请参阅此相关答案项(2))。
假设查询尝试使用快捷方式编写空比较:
select * from SomeTable
where IsNull(SomeNullableBitField, -1) != IsNull(SomeOtherNullableBitField, -1);
不同于
select * from SomeTable
where coalesce(SomeNullableBitField, -1) != coalesce(SomeOtherNullableBitField, -1);
因为在第一种情况下,IsNull()强制类型为一点(因此将-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)。
我没有看到明确指出的一个主要问题是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'
ISNULL uses the data type of the first parameter, COALESCE follows the CASE expression rules and returns the data type of value with the highest precedence.
该NULL
和COALESCE
并不总是可互换。它应该知道它们之间的差异,以便知道何时更好地使用它们:
上表为之间的比较ISNULL
,并COALESCE
从Exam Ref 70-761 Querying Data with Transact-SQL
由伊茨克奔甘写的书。
2
为ISNULL
VS>2
时使用COALESCE
ISNULL
是专有的T-SQL功能,并且COALESCE
是ISO / ANSI SQL标准结果的数据类型很重要。阅读上表中的注释后,请检查以下情况:
DECLARE @x VARCHAR(3) = NULL
,@y VARCHAR(10) = '1234567890';
SELECT ISNULL(@x, @y) AS [ISNULL], COALESCE(@x, @y) AS [COALESCE];
在ISNULL
越来越的第一个参数的数据类型,因为它是不
NULL
字面。它是VARCHAR(3)
与是一个结果,第二个参数数据被切割成相匹配。随着COALESCE
数据类型,如果使用最高优先级。
DECLARE @x VARCHAR(8) = '123x5'
,@y INT = 123;
SELECT ISNULL(@x, @y) AS [ISNULL];
SELECT COALESCE(@x, @y) AS [COALESCE];
在ISNULL
将返回第一个参数的数据类型,而
COALESCE
我们得到的错误,因为INT
具有最高的优先级,并第一个参数值的转换INT
失败。
结果的可为空性也很重要。例如:
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];
让我们检查Nullable
每一列的属性:
使用COALESCE
我们,只有当所有输入都是非空值时,才NOT NULL
将column的属性设置为Yes
。
根据SQL标准,该COALESCE
表达式被转换为:
CASE WHEN (<subquery>) IS NOT NULL THEN (<subquery>) ELSE 0 END
如果WHEN子句中子查询的执行结果不为NULL,则SQL Server在THEN子句中第二次执行它。换句话说,在这种情况下,它将执行两次。仅当WHEN子句中的执行结果为NULL时,SQL Server才不会再次执行子查询,而是返回ELSE表达式。因此,在使用子查询时,ISNULL函数具有性能优势。
如果只有一个空条件,ISNULL
则开销会更少。但是,差异可能微不足道。
ISNULL
吗?
COALESCE
可以互换使用,因此会带来更多开销。首先,ISNULL
处理固定数量的输入,其中COALESCE
指定用于任何数量的输入。其次,COALESCE
配置为返回具有最高数据类型优先级的表达式的数据类型,而ISNULL
返回与相同的类型check_expression
。就像我上面说的,在更高版本的SQL Server中,差异可能可以忽略不计,但严格来说,仍然存在开销。
这个解释清楚地说明了合并与非空
SQL中的COALESCE函数返回其参数中的第一个非NULL表达式。COALESCE的语法如下:
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
合并返回第一个非null表达式,其中使用isull()将null值替换为我们想要的值。
COALESCE是ANSI标准的一部分,几乎在所有数据库中都可用。
在ISNULL v COALESCE之间进行决定时,必须注意以下参数:
考虑以下sql语句
DECLARE @c5 VARCHAR(5);
SELECT 'COALESCE', COALESCE(@c5, 'longer name')
UNION ALL
SELECT 'ISNULL', ISNULL(@c5, 'longer name');
结果:
COALESCE longer name
ISNULL longe
发生这种情况是因为ISNULL采用第一个参数的数据类型,而COALESCE检查所有元素并选择最合适的值(在这种情况下为VARCHAR(11))
有关在COALESCE与ISNULL之间进行决定的更多详细说明,请检查:https : //www.mssqltips.com/sqlservertip/2689/deciding-between-coalesce-and-isnull-in-sql-server/
在COALESCE中,可以使用多个表达式,它将返回不为null且首先出现的值。例如
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中,如果expression null,它将返回提供的第二个参数,当然,您只能检查一个表达式...
因此,如果要检查多个表达式并首先选择其中的一个不为null,则使用合并,否则为ISNULL