您的位置:首页 > 数据库

详解SQL Server 比较带有尾随空格的字符串--【叶子】

2014-11-13 10:13 323 查看
前记:CSDN论坛上多次出现相关问题,总结一下个人对这个问题的看法,欢迎大家共同讨论。

1、问题描述

[sql] view
plaincopyprint?

declare @a varchar(10);set @a='maco '  

declare @b varchar(10);set @b='maco'  

if(@a=@b)  

    select '@a与@b相等'  

else  

    select '@a与@b不相等'  

--运行结果  

/*  

@a与@b相等  

*/  

@a后面有尾随空格,@b后面没有,但是为什么他们相等呢?

 

2、问题解析

2.1 有尾随空格的情况下,如何才能准确的比较两个字符串?

下面介绍几种常见的方式:

[sql] view
plaincopyprint?

declare @a varchar(10);set @a='maco '  

declare @b varchar(10);set @b='maco'  

  

--第一种方式(两边都加上常量)  

if(@a+'a'=@b+'a')  

    select '@a与@b相等' as 方式一结果  

else   

    select '@a与@b不相等' as 方式一结果  

[sql] view
plaincopyprint?

--第二种方式(替换空格未char(13))  

if(replace(@a,' ',char(13))=replace(@b,' ',char(13)))  

    select '@a与@b相等' as 方式二结果  

else  

    select '@a与@b不相等' as 方式二结果  

[sql] view
plaincopyprint?

--第三种方式(都转成varbinary类型后再比较)  

if(cast(@a as varbinary) = cast(@b as varbinary))  

    select '@a与@b相等' as 方式三结果  

else  

    select '@a与@b不相等' as 方式三结果  

[sql] view
plaincopyprint?

--第四种方式(判断datalength)  

if(@a=@b and datalength(@a)=datalength(@b))  

    select '@a与@b相等' as 方式四结果  

else   

    select '@a与@b不相等' as 方式四结果  

[sql] view
plaincopyprint?

--第五种方式(用like)  

if(@a=@b and @a like @b and @b like @a)  

    select '@a与@b相等' as 方式五结果  

else   

    select '@a与@b不相等' as 方式五结果  

  

--运行结果  

/*  

方式一结果  

------------  

@a与@b不相等  

  

(1 row(s) affected)  

  

方式二结果  

------------  

@a与@b不相等  

  

(1 row(s) affected)  

  

方式三结果  

------------  

@a与@b不相等  

  

(1 row(s) affected)  

  

方式四结果  

------------  

@a与@b不相等  

  

(1 row(s) affected)  

  

方式五结果  

------------  

@a与@b不相等  

  

(1 row(s) affected)  

*/  

这里特别要说明的是用len判断是不行的。

[sql] view
plaincopyprint?

declare @a varchar(10);set @a='maco '  

declare @b varchar(10);set @b='maco'  

if(@a=@b and len(@a)=len(@b))  

    select '@a与@b相等' as 方式六结果  

else   

    select '@a与@b不相等' as 方式六结果  

/*  

方式六结果  

----------  

@a与@b相等  

*/  

原因详见下图:



© 【叶子】http://blog.csdn.net/maco_wang 原创作品,转贴请注明作者和出处,留此信息。

 

2.2 为什么会出现这个问题,是尾随空格不参与比较吗?

个人认为不是这样的。

微软的帮助中曾经提到:ANSI 标准要求填充字符的字符串比较中使用,以使其长度匹配再进行比较。进行填充时,char 列用空格填充,binary 列用零填充。

LIKE 谓词表达式的右侧功能具有尾随空格的值时, SQL Server 不会填充到相同的长度在两个值比较发生之前。(上面的方式五,只是用like做个测试)

 

3、补充说明

说到尾随空格,不得不提到SET ANSI_PADDING

在 Microsoft SQL Server 的未来版本中,ANSI_PADDING 将始终为 ON,将该选项显式设置为 OFF 的任何应用程序都将产生错误。 请避免在新的开发工作中使用该功能,并着手修改当前还在使用该功能的应用程序。

SET ANSI_PADDING:对列存储长度小于列的定义大小的值以及在 char、varchar、binary 和 varbinary 数据中含有尾随空格的值的方式进行控制。

SET ANSI_PADDING虽然在比较的时候不起作用,但是它直接控制了入口,如果设置了off,则剪裁插入 varchar 列中的字符值的尾随空格。

详见:

设置
char(n) NOT NULL 或 binary(n) NOT NULL
char(n) NULL 或 binary(n) NULL
varchar(n) 或 varbinary(n)
ON
填充原始值(char 列具有尾随空格的值,binary 列具有尾随零的值),使达到列的长度。
如果 SET ANSI_PADDING 为 ON,则遵从与 char(n) 或 binary(n) NOT NULL 相同的规则。
不剪裁插入 varchar 列中的字符值的尾随空格。 不剪裁插入 varbinary 列中的二进制值的尾随零。 不将值填充到列的长度。
OFF
填充原始值(char 列具有尾随空格的值,binary 列具有尾随零的值),使达到列的长度。
如果 SET ANSI_PADDING 为 OFF,则遵从与 varchar 或 varbinary 相同的规则。
剪裁插入 varchar 列中的字符值的尾随空格。 剪裁插入 varbinary 列中的二进制值的尾随零。
 

注:建议始终将 ANSI_PADDING 设置为 ON。

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: