我最近在将 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# 中的 DataTable
访问时,[CanDoSomething]
列的值为 1
或 0
。当我们更改为使用 ISNULL
时,C# 中的值随后更改为 true
或 false
,当将其视为字符串时,显然不是与 1
或 0
相同。
由此引起的错误已经得到解决。我很好奇为什么 ISNULL
返回的值与等效的 CASE
语句不同,我似乎无法在 Google 上找到任何答案。
最佳答案
扩展@dasblinkenlight 的解释:
真正的问题是,根据 the documentation , case
表达式
return the highest precedence type from the set of types in *result_expressions* and the optional *else_result_expression*. For more information, see Data Type Precedence (Transact-SQL).
虽然 isnull()
returns the same type as *check_expression*
在您的例子中,这是一个位
。您的 case
表达式:
CASE
WHEN a.column1 IS NULL THEN 0
ELSE a.column1
END
具有返回两种不同数据类型的执行路径,int
(字面值 0
)和 bit
(值柱子)。如果您查看 data type precedence chart上面的链接中,int
的优先级高于 bit
,因此 bit
值被转换为 int
。
那是因为从 bit
到 int
的转换是一个加宽转换。 Sql Server 的 bit
类型本质上是一个 1 位整数值,因此不会丢失任何数据。从 int
到 bit
的转换是一个缩小转换,并且存在数据丢失的可能性(至少在概念上)。
如果 DBA 使用 coalesce()
,您就不会遇到此问题而不是 isnull()
,这本来是我个人的选择,因为 coalesce()
被定义为返回类似于 case
的类型. 合并()
Returns the data type of expression with the highest data type precedence. If all expressions are nonnullable, the result is typed as nonnullable.
关于c# - ISNULL 与 CASE 返回类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20430420/