1. 程式人生 > 其它 >關於MySQL自動將varchar型別值的末尾空格不起作用的問題

關於MySQL自動將varchar型別值的末尾空格不起作用的問題

背景

優化線上系統的一個查詢方法,這裡我舉例說明。
方法的功能是返回所有異常涉及到的容器號,並對其去重。
原來的方法是返回符合要求的Dto物件集合,然後取Dto物件中的containerNo這個屬性,通過map的key來實現去重操作;
現在的方法是在SQL層面只返回container_no欄位,且通過DISTICT 對容器號去重。
SQL內容類似於:

select distinct name  from  `user`  where name  = 'zhang';

我們假設資料庫中符合查詢條件的容器號有以下幾個:

  1. ZZW001
  2. ZZW002
  3. ZZW001 注意這裡末尾有一個空格
  4. ZZW001
    注意這裡末尾假設有三個空格

那麼新舊方法處理的結果是:

  • 舊方法:ZZW001 ZZW002 ZZW001 (注意這裡末尾有一個空格) ZZW001 (注意這裡末尾假設有三個空格)
  • 新方法:ZZW001 ZZW002

之所以這樣,是因為MySQL將字串後面的空格全給過濾了。
我也試了作為where 查詢條件,一樣是無效的,不過字串前面的空格是起作用的,且末尾的空格是可以正常儲存到資料庫裡的,即只有作為條件和資料處理物件時(比如去重),才會“失效”。

查閱了網上的資料,有人這麼說:

如果欄位是char或varchar型別,那麼在字串比較的時候MySQL使用PADSPACE校對規則,會忽略欄位末尾的空格字元。

解決方案:

第一種方法:使用 like

select * from table where user like 'abcdefg ';

第二種方法:使用BINARY

select * from table where user = BINARY 'abcdefg ';

第三種方法:使用length函式

select * from table where user = 'abcdefg ' and length(user) = length('abcdefg ');

注意

如果程式沒有對所有的業務場景做末尾空格的處理,那麼建議後面的查詢不要使用前面的解決方案來處理,否則容易出現問題,如果所有的業務場景在儲存資料的時候,都做了末尾空格的處理,那麼可以查詢的時候可以使用上面的解決方案來實現資料精確查詢。
其實對於資料的去重過濾如果資料不是特別的多,建議使用MySQL處理。以我們線上的這個問題為例,儲存容器號到業務表的時候,可能是使用者在末尾多輸入一個空格,末尾多空格依然可以查出資料,這個時候校驗就通過了,但是存到資料庫的拿使用者輸入的儲存的,即將末尾帶有空格的儲存了,如果後面使用前面的解決方案處理,就會出現問題,比如作為聯表查詢的時候關聯條件時。
但是程式碼的去重都是強校驗,末尾有空格和沒有空格是兩個不同的資料,所以就會出現最開始前面的背景問題。
最終,結合業務的分析,我們認為原來的方法是存在問題的,新方法在資料庫去重是沒問題的。