1、問題描述
- 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 有尾隨空格的情況下,如何才能準確的比較兩個字符串?
下面介紹幾種常見的方式:
- 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 方式一結果
- --第二種方式(替換空格未char(13))
- if(replace(@a,' ',char(13))=replace(@b,' ',char(13)))
- select '@a與@b相等' as 方式二結果
- else
- select '@a與@b不相等' as 方式二結果
- --第三種方式(都轉成varbinary類型後再比較)
- if(cast(@a as varbinary) = cast(@b as varbinary))
- select '@a與@b相等' as 方式三結果
- else
- select '@a與@b不相等' as 方式三結果
- --第四種方式(判斷datalength)
- if(@a=@b and datalength(@a)=datalength(@b))
- select '@a與@b相等' as 方式四結果
- else
- select '@a與@b不相等' as 方式四結果
- --第五種方式(用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判斷是不行的。
- 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相等
- */
原因詳見下圖:
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。
來源:【葉子】http://blog.csdn.net/maco_wang