詳解SQL Server 比較帶有尾隨空格的字符串

1、問題描述

  1. declare @a varchar(10);set @a='maco '  
  2. declare @b varchar(10);set @b='maco'  
  3. if(@a=@b)  
  4.     select '@a與@b相等'  
  5. else  
  6.     select '@a與@b不相等'  
  7. --運行結果  
  8. /*  
  9. @a與@b相等  
  10. */  

@a後面有尾隨空格,@b後面沒有,但是爲什麼他們相等呢?

 

2、問題解析

2.1 有尾隨空格的情況下,如何才能準確的比較兩個字符串?

下面介紹幾種常見的方式:

  1. declare @a varchar(10);set @a='maco '  
  2. declare @b varchar(10);set @b='maco'  
  3.   
  4. --第一種方式(兩邊都加上常量)  
  5. if(@a+'a'=@b+'a')  
  6.     select '@a與@b相等' as 方式一結果  
  7. else   
  8.     select '@a與@b不相等' as 方式一結果  
  1. --第二種方式(替換空格未char(13))  
  2. if(replace(@a,' ',char(13))=replace(@b,' ',char(13)))  
  3.     select '@a與@b相等' as 方式二結果  
  4. else  
  5.     select '@a與@b不相等' as 方式二結果  
  1. --第三種方式(都轉成varbinary類型後再比較)  
  2. if(cast(@a as varbinary) = cast(@b as varbinary))  
  3.     select '@a與@b相等' as 方式三結果  
  4. else  
  5.     select '@a與@b不相等' as 方式三結果  
  1. --第四種方式(判斷datalength)  
  2. if(@a=@b and datalength(@a)=datalength(@b))  
  3.     select '@a與@b相等' as 方式四結果  
  4. else   
  5.     select '@a與@b不相等' as 方式四結果  
  1. --第五種方式(用like)  
  2. if(@a=@b and @a like @b and @b like @a)  
  3.     select '@a與@b相等' as 方式五結果  
  4. else   
  5.     select '@a與@b不相等' as 方式五結果  
  6.   
  7. --運行結果  
  8. /*  
  9. 方式一結果  
  10. ------------  
  11. @a與@b不相等  
  12.   
  13. (1 row(s) affected)  
  14.   
  15. 方式二結果  
  16. ------------  
  17. @a與@b不相等  
  18.   
  19. (1 row(s) affected)  
  20.   
  21. 方式三結果  
  22. ------------  
  23. @a與@b不相等  
  24.   
  25. (1 row(s) affected)  
  26.   
  27. 方式四結果  
  28. ------------  
  29. @a與@b不相等  
  30.   
  31. (1 row(s) affected)  
  32.   
  33. 方式五結果  
  34. ------------  
  35. @a與@b不相等  
  36.   
  37. (1 row(s) affected)  
  38. */  

這裏特別要說明的是用len判斷是不行的。

  1. declare @a varchar(10);set @a='maco '  
  2. declare @b varchar(10);set @b='maco'  
  3. if(@a=@b and len(@a)=len(@b))  
  4.     select '@a與@b相等' as 方式六結果  
  5. else   
  6.     select '@a與@b不相等' as 方式六結果  
  7. /*  
  8. 方式六結果  
  9. ----------  
  10. @a與@b相等  
  11. */  

原因詳見下圖:



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 
發佈了57 篇原創文章 · 獲贊 6 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章