我最近遇到了一个有趣的问题,CASE即将语句更改为ISNULLTSQL中的函数.我正在使用的查询用于获取我工作的网站的一些用户属性和权限.以前,查询有许多CASE类似于以下的语句:
注意:a.column1在示例中是bit表中的类型.另请注意,[CanDoSomething]结果列有时用作网站中的字符串.
SELECT
...
CASE
WHEN a.column1 IS NULL THEN 0
ELSE a.column1
END [CanDoSomething]
...
FROM
a
Run Code Online (Sandbox Code Playgroud)
DBA用以下函数替换了这些CASE语句ISNULL:
SELECT
...
ISNULL(a.column1, 0) [CanDoSomething]
...
FROM
a
Run Code Online (Sandbox Code Playgroud)
这似乎是一个很好的改变,但它在C#中检索数据时引起了一些意想不到的事情.使用上一个查询,[CanDoSomething]从DataTableC#中访问时列的值是1或0.当我们改为使用时ISNULL,C#中的值随后被更改为true或者false,当被视为字符串时,显然与1or不同0.
这引起的错误已经得到解决.我只是好奇为什么ISNULL返回与同等CASE声明不同的值,而我似乎无法在Google上找到任何答案.
ISNULL ( check_expression , replacement_value )返回与...相同的类型
check_expression.如果NULL提供了文字check_expression,则返回replacement_value的数据类型.如果NULL提供了文字check_expression而没有replacement_value提供,则返回一个int.
不像你的CASE表达式总是返回*返回intint第一支零的,因为ISNULL将返回其第一个参数,即该类型的值a.column1.
CASE表达WHEN a.column1 IS NULL THEN 0 ELSE 1的编辑之前.
要扩展@ dasblinkenlight的解释:
真正的问题是,根据文档,case表达式
从*result_expressions*和可选的*else_result_expression*中的类型集返回最高优先级类型.有关更多信息,请参阅数据类型优先级(Transact-SQL).
而 isnull()
返回与*check_expression*相同的类型
在你的情况下,这是一个bit.你的case表达:
CASE
WHEN a.column1 IS NULL THEN 0
ELSE a.column1
END
Run Code Online (Sandbox Code Playgroud)
具有返回两种不同数据类型的执行路径,一个int(文字值0)和一个bit(列的值).如果查看上面链接的数据类型优先级图表,int其优先级高于bit,因此该bit值将转换为a int.
这是因为,从转换bit到int是扩大转换.Sql Server的bit类型本质上是1位整数值,因此没有数据丢失.从转换int到转换bit是一种缩小的转换,并且存在数据丢失的可能性(至少在概念上).
你不会遇到这个问题,如果DBA使用coalesce()而不是isnull(),这本来是我个人的选择,因为coalesce()被定义为返回类似于的类型case.coalesce()
返回具有最高数据类型优先级的表达式的数据类型.如果所有表达式都不可为空,则结果将输入为nonnullable.