MySQL的CHAR、VARCHAR、TEXT等字符串字段在等值比較("=")時,會忽略掉尾部的空格,導致有空格也能匹配上的坑

一、現象

CREATE TABLE `user_info` (
  `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主鍵自增ID',
  `user_name` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '名字',
 
  PRIMARY KEY (`id`),
  KEY `idx_user_name` (`user_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用戶表';
 
INSERT INTO user_info(user_name) values('lingyejun'); #無空格
INSERT INTO user_info(user_name) values('lingyejun '); #一個空格
INSERT INTO user_info(user_name) values('lingyejun    '); #四個空格

如上有個user_info表,我們分別插入'lingyejun'、'lingyejun '、'lingyejun    '三個用戶。

但我們在查詢時卻遇到一個詭異的現象:

SELECT * FROM user_info WHERE user_name = 'lingyejun'; #無空格
SELECT * FROM user_info WHERE user_name = 'lingyejun '; #一個空格
SELECT * FROM user_info WHERE user_name = 'lingyejun  '; #兩個空格
SELECT * FROM user_info WHERE user_name = 'lingyejun  '; #四個空格
 無論查詢中尾部帶有幾個空格,結果是一樣的,都會命中'lingyejun'、'lingyejun '、'lingyejun    '三個用戶。 

二、原因

查詢MySQL的官方文檔(https://dev.mysql.com/doc/refman/5.7/en/char.html),原來MySQL的校對規則基於PAD SPACE,這就意味着CHAR、VARCHAR、TEXT等字符串的等值比較(“=”)會忽略掉尾部的空格。 

而且這也符合SQL標準,無需設置也無法改變(參考:https://stackoverflow.com/questions/10495692/mysql-comparison-operator-spaces) 

三、想要精確查詢的解決方案

3.1 like

like不會忽略尾部的空格。

SELECT * FROM user_info WHERE user_name LIKE 'lingyejun';
SELECT * FROM user_info WHERE user_name LIKE 'lingyejun '; #一個空格
SELECT * FROM user_info WHERE user_name LIKE 'lingyejun    '; #四個空格

3.2 binary

binary不是函數,是類型轉換運算符,它用來強制它後面的字符串爲一個二進制字符串,可以理解成精確匹配。

SELECT * FROM user_info WHERE user_name = BINARY 'lingyejun';
SELECT * FROM user_info WHERE user_name = BINARY 'lingyejun '; #一個空格
SELECT * FROM user_info WHERE user_name = BINARY 'lingyejun    '; #四個空格

注:這裏的BINARY關鍵字要放在“=”的後邊,以便有效利用該字段的索引。

四、結論

  • MySQL的CHAR、VARCHAR、TEXT等字符串字段在等值比較("=")時,基於PAD SPACE校對規則,會忽略掉尾部的空格
  • 在存儲時,不會自動截斷尾部的空格,會按原值存儲
  • 如果想要精確查詢就不能用等值查詢(“=”),而應改用like或binary

 

本篇文章如有幫助到您,請給「翎野君」點個贊,感謝您的支持。

首發鏈接:https://www.cnblogs.com/lingyejun/p/17992543

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章