SQL WHERE子句将值与尾随空格匹配

时间:2010-11-12 15:30:28

标签: c# sql sql-server database sql-server-2008

在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 个答案:

答案 0 :(得分:65)

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

  

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

     

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

Source

答案 1 :(得分:6)

并不总是忽略尾随空格。 我今天遇到过这个问题。我的表有NCHAR列,并且正在加入VARCHAR数据。 由于表中的数据不如其字段宽,因此SQL Server会自动添加尾随空格。

我有一个采用varchar参数的ITVF(内联表值函数)。 这些参数用于JOIN到具有NCHAR字段的表格。

连接失败,因为传递给函数的数据没有尾随空格,但表中的数据没有。那是为什么?

我在DATA TYPE PRECEDENCE上被绊倒了。 (见http://technet.microsoft.com/en-us/library/ms190309.aspx

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

我是如何解决这个问题的?我将函数定义更改为使用NVARCHAR参数,这些参数的优先级高于NCHAR。现在,SQL Server自动将NCHAR更改为NVARCHAR,并忽略尾随空格。

为什么我不只是执行RTRIM?测试显示RTRIM杀死了性能,阻止了SQL Server本来会使用的JOIN优化。

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

答案 2 :(得分:3)

是的,马克是对的。运行以下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))

丑陋但是。

<强> EDIT2: 鉴于上述评论,以下内容可行:

select '"' + name + '"' from #temp where 'james' like name

答案 3 :(得分:-3)

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