日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
什么?MySQL的等值查詢竟然出錯(cuò)了?

1.問(wèn)題背景

前段時(shí)間,一個(gè)業(yè)務(wù)線的小伙伴大G找過(guò)來(lái),如下是我倆的對(duì)話。

柞水網(wǎng)站制作公司哪家好,找創(chuàng)新互聯(lián)公司!從網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開(kāi)發(fā)、APP開(kāi)發(fā)、響應(yīng)式網(wǎng)站開(kāi)發(fā)等網(wǎng)站項(xiàng)目制作,到程序開(kāi)發(fā),運(yùn)營(yíng)維護(hù)。創(chuàng)新互聯(lián)公司成立與2013年到現(xiàn)在10年的時(shí)間,我們擁有了豐富的建站經(jīng)驗(yàn)和運(yùn)維經(jīng)驗(yàn),來(lái)保證我們的工作的順利進(jìn)行。專注于網(wǎng)站建設(shè)就選創(chuàng)新互聯(lián)公司。

大G:云杰,聽(tīng)說(shuō)你MySQL挺厲害的,我最近遇到一個(gè)奇怪問(wèn)題,不知道你遇到過(guò)沒(méi),請(qǐng)教你下。

我:請(qǐng)教不敢當(dāng),我也就是個(gè)MySQL入門(mén)級(jí)選手,說(shuō)來(lái)看看。

大G:WHERE條件去等值查詢字符串,結(jié)果卻查出來(lái)幾條尾部有空格的,明明不相等。

我:不會(huì)吧?這么神奇,這個(gè)真沒(méi)遇到過(guò)!

大G:不信你試試!

我:試試就試試!

抱著求知的心態(tài),開(kāi)啟了本篇的探索之旅。

2.驗(yàn)證

2.1 數(shù)據(jù)準(zhǔn)備

首先在測(cè)試庫(kù)里建表,并準(zhǔn)備相關(guān)的原數(shù)據(jù)。創(chuàng)建個(gè)user_info表,分別插入'adu'(無(wú)空格)、'adu '(一個(gè)空格)、'adu    '(四個(gè)空格)三個(gè)用戶。

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('adu'); #無(wú)空格
INSERT INTO user_info(user_name) values('adu '); #一個(gè)空格
INSERT INTO user_info(user_name) values('adu '); #四個(gè)空格

2.2 問(wèn)題驗(yàn)證

2.2.1 尾部空格驗(yàn)證

SELECT * FROM user_info WHERE user_name = 'adu'; #無(wú)空格
SELECT * FROM user_info WHERE user_name = 'adu '; #一個(gè)空格
SELECT * FROM user_info WHERE user_name = 'adu '; #兩個(gè)空格
SELECT * FROM user_info WHERE user_name = 'adu '; #四個(gè)空格

我們使用如上條件去查,還真復(fù)現(xiàn)了!無(wú)論查詢中尾部帶有幾個(gè)空格,結(jié)果是一樣的,都會(huì)命中'adu'、'adu '、'adu    '三個(gè)用戶,結(jié)果如下圖所示(紅框圈起來(lái)的表示我們認(rèn)為不應(yīng)該出現(xiàn)的異常結(jié)果):

太神奇了!

2.2.2 頭部空格驗(yàn)證

那如果把空格放在前面呢?再來(lái)一把,結(jié)果如下:這下又匹配不上了??崭穹旁诤筮吙梢裕旁谇斑叢豢梢?,這太神奇了??!

2.2.3 唯一索引驗(yàn)證

那如果在user_name字段上建唯一索引,還能插入這三條記錄嗎?再來(lái)一把,結(jié)果如下:

也不行,被唯一索引約束住了。

2.2.4 長(zhǎng)度驗(yàn)證

那這三條記錄的user_name長(zhǎng)度又分別是多少呢?

確實(shí)長(zhǎng)度也不一樣。

2.3 驗(yàn)證小結(jié)

從結(jié)果上來(lái)看,明明是三個(gè)長(zhǎng)度不同的字符串,空格放在前邊被認(rèn)為是不同,放在后邊又被認(rèn)為是相同,而且唯一索引也沖突。我們有充足的理由懷疑MySQL忽略字符串尾部的空格,把'adu'、'adu '、'adu    '都當(dāng)成'adu'來(lái)處理。這確實(shí)超出了已有的認(rèn)知,那背后的原因究竟又是什么呢?

3.分析原因

查詢MySQL的官方文檔[1],原來(lái)跟字符串的校對(duì)規(guī)則有關(guān)。

原來(lái)MySQL的校對(duì)規(guī)則基于PAD SPACE,這就意味著CHAR、VARCHAR、TEXT等字符串的等值比較(“=”)會(huì)忽略掉尾部的空格,而且官網(wǎng)也說(shuō)了,適用于所有MySQL版本,并且不會(huì)改變。這。。。

既然MySQL官網(wǎng)說(shuō)的這么肯定,那么自信來(lái)自哪里呢?我們繼續(xù)追查SQL規(guī)范,原來(lái)SQL規(guī)范還真對(duì)這塊做了特別說(shuō)明[2],如下所示:

既然規(guī)范都這樣要求了,等值查詢“=”不能精確查詢,那么到底該如何精確地進(jìn)行等值查詢呢?

4.精確查詢的方法

通過(guò)調(diào)研,我們可以通過(guò)以下兩種方式進(jìn)行精確等值查詢。

4.1 LIKE

LIKE是基于逐個(gè)字符進(jìn)行比較的,這樣就不會(huì)忽略尾部的空格,官網(wǎng)對(duì)這塊也有特別的說(shuō)明。

那么我們?cè)偈褂肔IKE進(jìn)行等值查詢,結(jié)果還真可以!

4.2 BINARY

BINARY不是函數(shù),是類型轉(zhuǎn)換運(yùn)算符,它用來(lái)強(qiáng)制它后面的字符串轉(zhuǎn)為二進(jìn)制字節(jié),再逐個(gè)字節(jié)比較,也可以理解成精確匹配,官網(wǎng)[4]對(duì)這塊也有特別的說(shuō)明。

那么我們?cè)偈褂肂INARY進(jìn)行等值查詢,結(jié)果也是可以的。

5.總結(jié)

  • MySQL的CHAR、VARCHAR、TEXT等字符串字段在等值比較("=")時(shí),基于PAD SPACE校對(duì)規(guī)則,會(huì)忽略掉尾部的空格;
  • 在存儲(chǔ)時(shí),不會(huì)自動(dòng)截?cái)辔膊康目崭瘢瑫?huì)按原值存儲(chǔ);
  • 如果想要精確查詢就不能用等值查詢("="),而應(yīng)改用LIKE或BINARY;
  • 認(rèn)知有界,而求知無(wú)界。

關(guān)于作者

杜云杰,高級(jí)架構(gòu)師,轉(zhuǎn)轉(zhuǎn)架構(gòu)部負(fù)責(zé)人,轉(zhuǎn)轉(zhuǎn)技術(shù)委員會(huì)執(zhí)行主席,騰訊云TVP。負(fù)責(zé)服務(wù)治理、MQ、云平臺(tái)、APM、IM、分布式調(diào)用鏈路追蹤、監(jiān)控系統(tǒng)、配置中心、分布式任務(wù)調(diào)度平臺(tái)、分布式ID生成器、分布式鎖等基礎(chǔ)組件。

道阻且長(zhǎng),擁抱變化;而困而知,且勉且行。


網(wǎng)站題目:什么?MySQL的等值查詢竟然出錯(cuò)了?
當(dāng)前鏈接:http://www.dlmjj.cn/article/cogosgc.html