【问题标题】:Why is T-SQL ISNULL() truncating the string and COALESCE is not?为什么 T-SQL ISNULL() 截断字符串而 COALESCE 不截断?
【发布时间】:2013-09-23 23:33:33
【问题描述】:

鉴于以下情况:

SELECT ISNULL('XY' + NULL, 'ABCDEFGHIJ') -- Outputs ABC (Why?)
SELECT COALESCE('XY' + NULL, 'ABCDEFGHIJ') -- Outputs ABCDEFGHIJ

为什么这些语句返回不同的结果?

【问题讨论】:

    标签: sql-server tsql coalesce isnull truncation


    【解决方案1】:

    根据微软documentation,功能:

    ISNULL(check_expression, replacement_value)
    

    replacement_value 必须是可隐式转换为check_expression 类型的类型。请注意'xy'+NULL 的类型是VARCHAR(3)。因此,您的字符串 'ABCDEFGHIJ' 被强制转换为 VARCHAR(3) 并因此被修剪。

    为什么不是VARCHAR(2) 听起来很奇怪,但事实就是这样——比'xy' 长一个字符。您可以使用这个 SQLFiddle 并亲自查看'xy'+NULL 的类型与表达式CASE WHEN 1=2 THEN 'XYZ' ELSE NULL END 相同,即NULL 但隐式兼容VARCHAR(3)

    对于表达式'xy'+NULL,感知长度似乎可以计算为'xy' 字符串长度(2)加上每添加一个NULL 1。例如,'xy'+NULL+NULL 的类型是 VARCHAR(4)'xy'+NULL+NULL+NULL 的类型是 VARCHAR(5) 等等 - 看看这个 SQLFiddle。这非常奇怪,但这就是 MS SQL Server 2008 和 2012 的工作方式。

    【讨论】:

    • 很好的解释,虽然我不相信 varchar(3) 而不是 varchar(2) - 我在任何地方都找不到它的文档。
    • 我必须增加这里的信息来解释更多关于 COALESCE 行为而不是 ISNULL 行为的信息,来自 Microsoft documentation:COALESCE 表达式是 CASE 表达式的语法快捷方式。也就是说,查询优化器将代码 COALESCE(expression1,...n) 重写为以下 CASE 表达式: CASE WHEN (expression1 IS NOT NULL) THEN expression1 WHEN (expression2 IS NOT NULL) THEN expression2 ... ELSE expressionN END -> case 返回类型由最高的 expr 优先级给出。
    • 这解释了COALESCE 的行为,但没有说明为什么'xy'+NULL 的类型是VARCHAR(3)。这一定与 SQL Server 内部有关。
    • 我不确定我是否得到了你的样品证明。第二个查询是一个 varchar(3) 因为 'XYZ' 而不是因为 NULL 的 CASE,对吧?所以我猜剩下的疑问是关于 'X'+NULL 变成 varchar(2) 而不是 varchar(1)。那么,在这种情况下,NULL 是否被视为单个字符?使用 ISNULL 连接字符串时是否需要担心溢出/截断?
    • 是的,NULL 增加了 1 个字符。这很奇怪,但这里有确凿的证据:sqlfiddle.com/#!3/d41d8/20994
    【解决方案2】:

    【讨论】:

    • +1 为博客文章,我在第一次研究时没有注意到它。很好的资源。
    【解决方案3】:

    ISNULL() 将替换值转换为检查表达式的类型。在这种情况下,检查表达式的类型是CHAR(2),因此转换替换值会截断它(你确定你得到的是ABC 而不仅仅是AB?)。

    来自微软documentation

    如果replacement_valuecheck_expression 长,replacement_value 可以被截断。

    【讨论】:

      猜你喜欢
      • 2019-01-03
      • 2015-12-20
      • 1970-01-01
      • 2021-10-28
      • 1970-01-01
      • 2014-09-14
      • 2015-12-14
      • 1970-01-01
      相关资源
      最近更新 更多