one*_*hen 56
Microsoft Connect上报告的此问题显示COALESCE和之间存在一些差异ISNULL:
我们处理的早期部分重写
COALESCE( expression1, expression2 )为CASE WHEN expression1 IS NOT NULL THEN expression1 ELSE expression2 END.在[这个例子]中:Run Code Online (Sandbox Code Playgroud)COALESCE ( ( SELECT Nullable FROM Demo WHERE SomeCol = 1 ), 1 )我们生成:
Run Code Online (Sandbox Code Playgroud)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,因为后者不会复制子查询.
Gol*_*rol 24
我认为不是,但COALESCE符合SQL '92标准,并受更多不同数据库的支持.如果你想要便携性,不要使用ISNULL.
小智 11
在COALESCE中,您可以拥有多个表达式,而在ISNULL中,您只能检查一个表达式
COALESCE ( expression [ ,...n ] )
ISNULL ( check_expression , replacement_value )
Run Code Online (Sandbox Code Playgroud)
值得一提的是,两者之间的类型处理也会有所不同(参见相关答案项目(2)).
假设查询尝试使用快捷方式来编写空比较:
select * from SomeTable
where IsNull(SomeNullableBitField, -1) != IsNull(SomeOtherNullableBitField, -1);
Run Code Online (Sandbox Code Playgroud)
这与...不同
select * from SomeTable
where coalesce(SomeNullableBitField, -1) != coalesce(SomeOtherNullableBitField, -1);
Run Code Online (Sandbox Code Playgroud)
因为在第一种情况下,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;
Run Code Online (Sandbox Code Playgroud)
关于问题本身也有类似的评论/链接(@Martin Smith).
该NULL和COALESCE并不总是可互换。应该了解它们的差异,以便知道何时使用一个比另一个更好:
上表为之间的比较ISNULL,并COALESCE从Exam Ref 70-761 Querying Data with Transact-SQL由伊茨克奔甘写的书。
2for ISNULLvs>2使用时COALESCEISNULL是专有的 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];
Run Code Online (Sandbox Code Playgroud)
在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];
Run Code Online (Sandbox Code Playgroud)
在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];
Run Code Online (Sandbox Code Playgroud)
让我们检查Nullable每一列的属性:
使用COALESCE我们将NOT NULLcolumn的属性设置为Yes,仅当所有输入都不能为空时。
根据 SQL 标准,COALESCE表达式被翻译为:
CASE WHEN (<subquery>) IS NOT NULL THEN (<subquery>) ELSE 0 END
Run Code Online (Sandbox Code Playgroud)
如果 WHEN 子句中子查询的执行结果不为 NULL,SQL Server 将在 THEN 子句中再次执行它。换句话说,在这种情况下,它会执行两次。只有当 WHEN 子句中的执行结果为 NULL 时,SQL Server 才不会再次执行子查询,而是返回 ELSE 表达式。所以在使用子查询时,ISNULL 函数具有性能优势。
我没有看到明确指出的一个主要问题是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'
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
46224 次 |
| 最近记录: |