ISNULL vs CASE返回类型

时间:2013-12-06 17:53:56

标签: c# sql tsql

我最近在TSQL中将CASE语句更改为ISNULL函数时遇到了一个有趣的问题。我正在使用的查询用于获取我工作的网站的一些用户属性和权限。以前,该查询有许多类似于以下内容的CASE语句:

注意:示例中的a.column1在表中的类型为bit。另请注意,[CanDoSomething]结果列有时用作网站中的字符串。

SELECT
    ...
    CASE
        WHEN a.column1 IS NULL THEN 0
        ELSE a.column1
    END [CanDoSomething]
    ...
FROM
    a

DBA用CASE函数替换了这些ISNULL语句:

SELECT
    ...
    ISNULL(a.column1, 0) [CanDoSomething]
    ...
FROM
    a

这似乎是一个很好的改变,但是在C#中检索数据时会出现意外情况。使用上一个查询,从C#中的[CanDoSomething]访问时DataTable列的值为10。当我们更改为使用ISNULL时,C#中的值随后更改为truefalse,当被视为字符串时,显然与10

这引起的错误已经得到解决。我只是好奇为什么ISNULL返回的值不同于同等的CASE语句,我似乎无法在Google上找到任何答案。

2 个答案:

答案 0 :(得分:5)

答案是documentation of ISNULL's return type

  

ISNULL ( check_expression , replacement_value )

     

返回与check_expression相同的类型。如果文字NULL作为check_expression提供,则返回replacement_value的数据类型。如果提供的文字NULLcheck_expression且未提供replacement_value,则返回int

CASE表达式不同,始终返回int * 返回int,因为第一个分支中为零, ISNULL将返回其第一个参数类型的值,即a.column1

<小时/> * 编辑前CASE表达式为WHEN a.column1 IS NULL THEN 0 ELSE 1

答案 1 :(得分:5)

扩展@ dasblinkenlight的解释:

真正的问题是,每the documentationcase个表达式

  

从中输入类型集中的最高优先级类型   * result_expressions *和可选的* else_result_expression *。   有关详细信息,请参阅Data Type Precedence (Transact-SQL)

isnull()

  

返回与* check_expression *

相同的类型

在您的情况下,这是bit。您的case表达式:

CASE
  WHEN a.column1 IS NULL THEN 0
  ELSE                        a.column1
END

具有返回两种不同数据类型的执行路径,int(文字值0)和bit(列的值)。如果您查看上面链接的data type precedence chart,则int的优先级高于bit,因此bit值会转换为int

这是因为从bitint的转换是扩展转换。 Sql Server的bit类型本质上是1位整数值,因此没有数据丢失。从intbit的转换是缩小转化,并且存在数据丢失的可能性(至少在概念上)。

如果DBA使用了coalesce()而不是isnull(),这本来是我个人的选择,你不会遇到这个问题,因为coalesce()被定义为返回一个类型类似于casecoalesce()

  

返回具有最高数据类型优先级的表达式的数据类型。如果所有表达式都是不可为空的,则结果将被输入为nonnullable。