SQL WHERE子句将值与尾随空格匹配
在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()
将其删除,表明它是某种空白字符。
谁能帮忙?
这是预期的结果:在SQL Server中, =
运算符在进行比较时会忽略尾随空格。
SQL Server遵循ANSI / ISO SQL-92规范(第8.2节,一般规则#3)关于如何将string与空格进行比较。 ANSI标准要求在比较中使用填充string,以便在比较之前匹配它们的长度。 填充直接影响WHERE和HAVING子句谓词的语义以及其他Transact-SQLstring比较。 例如,Transact-SQL认为string“abc”和“abc”对于大多数比较操作是等价的。
这个规则唯一的例外是LIKE谓词。 当LIKE谓词expression式的右侧具有带尾随空格的值时,在比较发生之前,SQL Server不会将这两个值填充到相同的长度。 由于定义LIKE谓词的目的是为了方便模式search而不是简单的string相等性testing,所以这并不违反前面提到的ANSI SQL-92规范的一部分。
资源
尾随空格并不总是被忽略。 我今天遇到这个问题。 我的表有NCHAR列,正在join到VARCHAR数据。 由于表中的数据不及其字段的宽度,所以SQL Server会自动添加尾随空格。
我有一个ITVF(内联表值函数)采取varchar参数。 参数用于与NCHAR字段的JOIN表中。
连接失败,因为传递给函数的数据没有尾随空格,但表中的数据没有。 为什么呢?
数据types优先级,我被绊倒了。 (请参阅http://technet.microsoft.com/en-us/library/ms190309.aspx )
在比较不同types的string时,较低优先级types在比较之前转换为较高优先级types。 所以我的VARCHAR参数被转换成NCHARs。 NCHARs进行了比较,显然空间是显着的。
我是如何解决这个问题的? 我改变了函数定义来使用比NCHAR更高优先级的NVARCHAR参数。 现在,NCHAR被SQL Server自动更改为NVARCHAR,并且尾部空格被忽略。
为什么我不只是做一个RTRIM? testing表明,RTRIM杀死了性能,阻止了SQL Server本来使用的JOIN优化。
为什么不改变表的数据types? 这些表已经安装在客户站点上,他们不想运行维护脚本(时间+金钱来支付DBA),或者让我们访问他们的机器人(可以理解)。
是的,马克是正确的。 运行以下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
尝试
select Replace('"' + ZoneReference + '"'," ", "") as QuotedZoneReference from Zone where ZoneReference = 'WF11XU'