我有点今早奇跑进东西我想我会提交的评论。
有人可以解释为什么下面的SQL查询打印“平等”时,针对SQL 2008中运行的数据库兼容级别设置为100。
if '' = ' '
print 'equal'
else
print 'not equal'
而这个返回0:
select (LEN(' '))
这似乎是自动微调的空间。 我不知道这是否是在SQL Server的早期版本的情况下,我不再有任何左右,甚至对其进行测试。
我遇到了这一点,因为生产的查询返回了不正确的结果。 我找不到这种行为记录任何地方。
有没有人有这方面的消息?
Answer 1:
varchar
S和平等是在TSQL棘手。 该LEN
函数说:
返回的字符数,而不是给定的字节串表达式的数量, 不包括尾随空白 。
您需要使用DATALENGTH
得到真正byte
有问题的数据的数量。 如果你有Unicode数据,请注意,在这种情况下获得的价值将不一样的文本的长度。
print(DATALENGTH(' ')) --1
print(LEN(' ')) --0
当涉及到表达的平等,这两个字符串像这种平等比较:
- 获得较短的字符串
- 垫用空格直到长度等于较长的字符串
- 比较两个
这是造成意外的结果,中间一步 - 这一步之后,你是比较有效的打击空白空白 - 因此,他们被看作是平等的。
LIKE
表现优于=
在“空白”的情况,因为它不执行你试图匹配模式的空白填充:
if '' = ' '
print 'eq'
else
print 'ne'
会给eq
同时:
if '' LIKE ' '
print 'eq'
else
print 'ne'
会给ne
小心LIKE
虽然:它不是对称的:它把结尾的空白图案中的(RHS),但不匹配表达式(左轴)作为显著。 以下是取自这里 :
declare @Space nvarchar(10)
declare @Space2 nvarchar(10)
set @Space = ''
set @Space2 = ' '
if @Space like @Space2
print '@Space Like @Space2'
else
print '@Space Not Like @Space2'
if @Space2 like @Space
print '@Space2 Like @Space'
else
print '@Space2 Not Like @Space'
@Space Not Like @Space2
@Space2 Like @Space
Answer 2:
=操作符是T-SQL与其说“等于”,因为它是“相同词/短语,根据表达式的上下文的整理”和LEN是“的词/短语的字符数”。 没有归类的治疗尾随空白作为词/短语的一部分,之前他们(虽然他们把前面的空格,因为它们先于字符串的一部分)。
如果您需要区别于“这个”“这个”,你不应该用“是同一个词或短语”运算符,因为“这个”和“本”是同一个词。
特约=的工作方式是,字符串平等运营商应取决于它的参数的内容和表达的整理方面的想法,但它不应该依赖于类型的参数,如果它们都是字符串类型。
的“这些都是同一个词”自然语言的概念通常不足够精确,以便能够通过像=数学运算符被捕获,而且也没有在自然语言字符串类型的概念。 上下文(即整理)事项(以及自然语言存在),是故事的一部分,和其他属性(一些看似古怪的)是为了使非自然世界里明确=的定义的一部分数据。
在类型的问题,你不希望的话,当他们存储在不同的字符串类型改变。 例如,类型VARCHAR(10),CHAR(10)和CHAR(3)持有的所有单词 '猫' 的表示,和? =“猫”应该让我们决定,如果任何这些类型的值保存的是“猫”(由归类决定的大小写和重音的问题)。
回应JohnFx的评论:
请参阅使用CHAR和VARCHAR数据联机丛书。 从该页面,重点煤矿报价:
每个char和varchar数据值具有排序规则。 归类定义属性,诸如用于每个字符, 比较规则 ,和灵敏度表示到壳体或重音的位模式。
我同意它可能是更容易找到,但它的记录。
值得一提的,也就是SQL的语法,其中=必须与现实世界的数据和比较的情况下做的(而不是一些关于存储在计算机上的位)已经很长一段时间SQL的一部分。 的RDBMS和SQL的前提是真实世界的数据的忠实代表,因此它的排序规则的支持,很多年以前类似的想法(如CultureInfo的)进入类ALGOL语言的境界。 这些语言(至少直到最近)的前提是解决问题的工程,而不是业务数据的管理。 (最近,使用非工程应用,如搜索类似的语言正在采取一些进展,但Java,C#等仍与它们的非businessy根挣扎。)
在我看来,这是不公平的批评SQL的不同于“大多数的编程语言。” SQL旨在支持企业数据建模这是从工程非常不同的框架,所以语言是不同的(和它的目标更好)。
哎呀,当第一次被指定SQL,一些语言没有任何内置的字符串类型。 而且在某些语言尽管如此,等于串并没有在所有的字符数据之间的比较操作,但比较的参考! 如果在十年或二十年,即==想法是文化依赖成为常态它不会让我感到吃惊。
Answer 3:
我发现这个博客文章中描述的行为,并解释了原因。
SQL标准要求字符串比较,有效,垫较短的字符串空格字符。 这导致了令人惊奇的结果N“” = N”'(空字符串等于的一个或多个空格字符的字符串)以及更一般的任何字符串等于另一个字符串,如果他们的差异仅在于尾部空格。 这可能是在某些情况下的一个问题。
更多信息,同时有MSKB316626
Answer 4:
有一个类似的问题前一段时间,我看着一个类似的问题在这里
相反LEN(“‘)的,使用DATALENGTH(’”) - ,为您提供正确的值。
该解决方案是使用LIKE子句在那里我的回答解释,和/或包含在WHERE子句中第2个条件检查DATALENGTH了。
有这个问题,并在那里链接的读取。
Answer 5:
要比较一个值,文字的空间,你也可以使用此技术作为一种替代LIKE语句:
IF ASCII('') = 32 PRINT 'equal' ELSE PRINT 'not equal'
Answer 6:
有时候,一个人应对空间中的数据,有或没有任何其它字符,即使使用空的想法是更好 - 但并不总是使用。 我也碰到所描述的情况,并解决了它这种方式:
...其中( '>' + @space + '<')<>( '>' + @空间2 + '<')
当然,你不会这么做的FPR大量的数据,但它工作快速,轻松几百行...
赫伯特
Answer 7:
如何不重复的记录上选择与SQL Server上的字段CHAR / VARCHAR:例如:
declare @mayvar as varchar(10)
set @mayvar = 'data '
select mykey, myfield from mytable where myfield = @mayvar
预期
的myKey(INT)| MyField的(varchar10)
1 | “数据”
获得
的myKey | MyField的
1 | '数据' 2 | “日期”
即使我写select mykey, myfield from mytable where myfield = 'data'
(没有最后的空白),我得到了相同的结果。
我该怎么解决呢? 在这种模式下:
select mykey, myfield
from mytable
where myfield = @mayvar
and DATALENGTH(isnull(myfield,'')) = DATALENGTH(@mayvar)
并且如果存在于MyField的一个索引,它会被在每种情况下使用。
我希望这将是有益的。
Answer 8:
另一种方法是把它放回了空间具有价值的状态。 例如:已知像一个字符替换空间_
if REPLACE('hello',' ','_') = REPLACE('hello ',' ','_')
print 'equal'
else
print 'not equal'
返回:不等于
不理想,可能是缓慢的,但另一种快速前进的方向需要时迅速。
文章来源: SQL Server 2008 Empty String vs. Space