代码之家  ›  专栏  ›  技术社区  ›  Neil Barnwell

与尾随空格匹配的SQL WHERE子句

  •  43
  • Neil Barnwell  · 技术社区  · 14 年前

    在SQL Server 2008中,我有一个名为 Zone 用柱 ZoneReference varchar(50) not null 作为主键。

    如果我运行以下查询:

    select '"' + ZoneReference + '"' as QuotedZoneReference
    from Zone
    where ZoneReference = 'WF11XU'
    

    我得到以下结果:

    "WF11XU "
    

    注意尾随空格。

    这怎么可能?如果尾随空格真的在那一行,那么我希望返回 结果,所以我假设SQL Server Management Studio还显示了一些奇怪的东西。

    在C代码调用中 zoneReference.Trim() 删除它,表明它是某种空白字符。

    有人能帮忙吗?

    4 回复  |  直到 6 年前
        1
  •  65
  •   Mark Byers    14 年前

    这是预期的结果:在SQL Server中, = 运算符在进行比较时忽略尾随空格。

    SQL Server遵循关于如何将字符串与空格进行比较的ANSI/ISO SQL-92规范(第8.2节,一般规则3)。ANSI标准要求对比较中使用的字符串进行填充,以使其长度在比较之前匹配。填充直接影响WHERE和HAVING子句谓词以及其他Transact-SQL字符串比较的语义。例如,Transact-SQL认为字符串“abc”和“abc”对于大多数比较操作都是等效的。

    唯一的例外是like谓词。当相似谓词表达式的右侧具有带尾随空格的值时,SQL Server不会在比较之前将这两个值填充到相同的长度。因为根据定义,LIKE谓词的目的是方便模式搜索,而不是简单的字符串相等性测试,所以这不会违反前面提到的ANSISQL-92规范的部分。

    Source

        2
  •  6
  •   Paul Chernoch    11 年前

    尾随空格并不总是被忽略。 我今天经历了这个问题。我的表有NChar列,正在与varchar数据联接。 因为表中的数据不如其字段宽,所以SQL Server会自动添加尾随空格。

    我有一个采用varchar参数的itvf(内联表值函数)。 这些参数用于与带有nchar字段的表的联接中。

    联接失败,因为传递给函数的数据没有尾随空格,但表中的数据有尾随空格。为什么会这样?

    我被数据类型优先权绊倒了。(见 http://technet.microsoft.com/en-us/library/ms190309.aspx )

    比较不同类型的字符串时,在比较之前,低优先级类型将转换为高优先级类型。所以我的varchar参数被转换成nchars。对NChars进行了比较,显然这些空间非常重要。

    我是怎么修好的?我更改了函数定义以使用nvarchar参数,这些参数的优先级高于nchar。现在,NChars被SQL Server自动更改为nvarchars,尾部空格被忽略。

    为什么我不做一个RTRIM?测试显示,RTRIM破坏了性能,从而阻止了SQL Server否则将使用的连接优化。

    为什么不更改表的数据类型?这些表已经安装在客户站点上,他们不想运行维护脚本(时间+支付DBA的费用)或让我们访问他们的机器(可以理解)。

        3
  •  3
  •   Mutation Person    14 年前

    是的,马克是对的。运行以下SQL:

    create table #temp (name varchar(15))
    insert into #temp values ('james ')
    select '"' + name + '"' from #temp where name ='james'
    select '"' + name + '"' from #temp where name like 'james'
    drop table #temp
    

    但是,在上面的示例中,关于“like”语句的断言似乎不起作用。输出:

    (1 row(s) affected)
    
    -----------------
    "james "
    
    (1 row(s) affected)
    
    
    -----------------
    "james "
    
    (1 row(s) affected)
    

    编辑: 为了让它发挥作用,你可以把它放在最后:

    and name <> rtrim(ltrim(name))
    

    虽然丑陋。

    编辑2: 鉴于上述评论,以下内容将起作用:

    select '"' + name + '"' from #temp where 'james' like name
    
        4
  •  -3
  •   byte_slave    14 年前

    尝试

        select Replace('"' + ZoneReference + '"'," ", "") as QuotedZoneReference from Zone where ZoneReference = 'WF11XU'