为什么案例中的一个场景的内容决定了对方的内容是否应该被正确修剪?

时间:2015-09-30 11:15:43

标签: sql sql-server

我的同事和我在SQL-Server中遇到了一个奇怪的行为。

请考虑以下代码:

select a = 
    case when 1=1 then
        'a '
    else
        'b '
    end + 'c'

应该合理地假设上面的代码产生字符串'a c'。确实如此。

但是,如果我用额外的空格扩展else的常量('b'),会发生奇怪的事情:

select a = 
    case when 1=1 then
        'a '
    else
        'b  '
    end + 'c'

现在结果是'ac','a'的空间消失了。反之亦然:

select a = 
    case when 1=0 then
        'a  '
    else
        'b '
    end + 'c'

这将产生'bc'。因此,无论返回的常量是否超过返回的常量,返回的常量都会被右边修剪。

它只是一个正确的修剪,因为以下代码将产生'ac':

select a = 
    case when 1=1 then
        ' a '
    else
        'b   '
    end + 'c'

这种行为有原因吗?我假设它可能与清理字符串尾随空格有关,但是为什么它只发生在未返回的常量更长时间?

在SQL Server 2014 Express Edition上已观察到上述行为。

更新

如评论中所述,在SQL Server 2014的标准安装中,此行为似乎无法重现。

1 个答案:

答案 0 :(得分:3)

您的会话看起来像SET ANSI_PADDING OFF,它会修剪varchar的尾随空格。尝试使用SET ANSI_PADDING ON(推荐设置)运行。

SET ANSI_PADDING OFF;

--trims trailing spaces
SELECT a = 
    CASE WHEN 1=1 THEN
        'a '
    ELSE
        'b  '
    END + 'c';

--does not trim trailing spaces
SET ANSI_PADDING ON;

SELECT a = 
    CASE WHEN 1=1 THEN
        'a '
    ELSE
        'b  '
    END + 'c';

修改

根据SQL Server ANSI_PADDING documentation,该设置应仅适用于列存储,而不适用于表达式结果。我询问了这种行为,SQL Server MVP Erland Sommarskog使用古老的SQL Server版本进行了一些回归测试,并将此行为识别为SQL 7中引入的错误。它已在SQL 2000中得到纠正,但仅适用于ANSI_PADDING ON; ANSI_PADDING OFF到目前为止仍然行为不端。

我强烈建议您更改代码,以免依赖于无证件和错误的行为。可能会在将来的SQL Server版本或修补程序中修复此错误并破坏您的代码。如果您的应用程序需要删除尾随空格,请明确使用RTRIM函数。