<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          一條詭異的insert語句

          共 2060字,需瀏覽 5分鐘

           ·

          2021-12-01 00:30

          點(diǎn)擊上方“碼農(nóng)突圍”,馬上關(guān)注

          這里是碼農(nóng)充電第一站,回復(fù)“666”,獲取一份專屬大禮包
          真愛,請(qǐng)?jiān)O(shè)置“星標(biāo)”或點(diǎn)個(gè)“在看


          作者 | 天士夢(mèng)
          來源 | https://www.cnblogs.com/cchust/p/4601536.html
          問題背景
          有同事反饋在mysql上面執(zhí)行一條普通的insert語句,結(jié)果報(bào)錯(cuò),
          execute failed due to >>> Incorrect string value: '\xA1;offl...' for column 'biz_info' at row 1
          經(jīng)過半天的折騰,終于搞清楚了來龍去脈,這里簡(jiǎn)單給大家分享下。為了方便說明,我將測(cè)試?yán)又械谋砗驼Z句簡(jiǎn)化,但不影響問題重現(xiàn)。

          問題復(fù)現(xiàn)

          連接字符集:UTF8

          表結(jié)構(gòu):
          CREATE?TABLE?`ggg`?(
          ??`id`?int(11)?DEFAULT?NULL,
          ??`c`?varchar(100)?DEFAULT?NULL
          )?ENGINE=InnoDB?DEFAULT?CHARSET=gbk;
          root@test?06:13:48>insert?into?ggg?values(1,concat('cardName:校園網(wǎng)',char(59),'offlineCardType:campus'));
          Query?OK,?1?row?affected,?1?warning?(2.51?sec)
          root@test?06:14:36>show?warnings\G
          ***************************?1.?row?***************************
          Level:?Warning
          Code:?1366
          Message:?Incorrect?string?value:?'\x91;offl...'?for?column?'c'?at?row?1?
          查看結(jié)果
          root@test?06:16:06>select?*?from?ggg?where?id=1;
          ***************************?1.?row?***************************
          id:?1
          c:?cardName:鏍″洯緗

          問題分析

          從報(bào)錯(cuò)的結(jié)果來看,感覺是字符集轉(zhuǎn)換引起的問題,而且由于連接串的字符集是UTF8,表的字符集是GBK,更容易引起懷疑。但是,即使是字符集轉(zhuǎn)換,也不應(yīng)該導(dǎo)致插入報(bào)錯(cuò),因?yàn)檎Z句中的中文字符“校園網(wǎng)"都是普通漢字,UTF8->GBK不應(yīng)該存在問題。
          那我們?cè)诨剡^頭來看看insert語句,唯一特殊的是使用了concat和char兩個(gè)函數(shù)。會(huì)不會(huì)跟這兩個(gè)函數(shù)有關(guān)系?char(59)實(shí)際是字符“;”,為了驗(yàn)證想法,做了兩個(gè)實(shí)驗(yàn):
          將char(59)替換成';'
          insert into ggg values(1,concat('cardName:校園網(wǎng)',';','offlineCardType:campus'));

          設(shè)置連接串字符集為GBK

          insert into ggg values(1,concat('cardName:校園網(wǎng)',char(59),'offlineCardType:campus'));
          果然,兩種情況執(zhí)行結(jié)果都是OK的,查詢結(jié)果如下:
          root@test?09:22:32>select?*?from?ggg\G
          ***************************?1.?row?***************************
          id:?1
          c:?cardName:鏍″洯緗
          ***************************?2.?row?***************************
          id:?1
          c:?cardName:校園網(wǎng);offlineCardType:campus
          ***************************?3.?row?***************************
          id:?1
          c:?cardName:校園網(wǎng);offlineCardType:campus
          跟蹤了下源代碼,找到了原因。char()函數(shù)返回的是一個(gè)binary類型字符串,在進(jìn)行concat時(shí),會(huì)導(dǎo)致'cardName:校園網(wǎng)'字符串到binary的轉(zhuǎn)換。轉(zhuǎn)換前,mysql將字符串‘cardName:校園網(wǎng)’看作是9個(gè)英文字符和3個(gè)漢字字符;轉(zhuǎn)換后,mysql將其看作是18個(gè)字節(jié)的二進(jìn)制串,其中,UTF8字符集的三個(gè)漢字“校園網(wǎng)”占了9個(gè)字節(jié)。由于目標(biāo)表字符集是GBK,因此在入庫(kù)時(shí),還會(huì)發(fā)生一次binary到GBK的轉(zhuǎn)碼,“校園網(wǎng)”的二級(jí)制編碼是E6A0A1 E59BAD E58DA1,在轉(zhuǎn)碼過程中,由于GBK字符集只包含一個(gè)字節(jié)(編碼值<128)和二個(gè)字節(jié)的字符(漢字和特殊字符),“校園網(wǎng)”的二進(jìn)制串會(huì)按照兩個(gè)字節(jié)拆分E6A0 A1E5 9BAD E58D A1,前面四個(gè)變?yōu)椤版牎鍥|”,解析到A1時(shí),由于A1既不是單字節(jié)字符,又不能與后面的字節(jié)組成一個(gè)合法的GBK字符,導(dǎo)致轉(zhuǎn)換出錯(cuò)。
          現(xiàn)在就很好解釋為啥改變語句后,兩種情況都OK了。第一種情況,將char(59)直接替換成‘;’,由于不涉及UF8到binary的轉(zhuǎn)換,只有utf8到gbk轉(zhuǎn)碼的過程,這個(gè)轉(zhuǎn)換是OK的,不會(huì)出現(xiàn)亂碼;第二種情況,將連接串的字符集設(shè)置為GBK,那么會(huì)涉及GBK到binary的轉(zhuǎn)換,然后再?gòu)腷inary轉(zhuǎn)換到GBK,由于整個(gè)轉(zhuǎn)換過程并沒有二進(jìn)制數(shù)據(jù)丟失,所以也是OK的。

          問題產(chǎn)生的兩個(gè)關(guān)鍵點(diǎn)

          1. 連接字符集與表字符集不匹配
          2. 使用了char函數(shù)

          解決辦法

          1.char函數(shù)提供了using語法來實(shí)現(xiàn)返回特定字符集的字符串,比如:char(59 using utf8)
          2.保證連接字符集與表字符集一致。

          -End-

          最近有一些小伙伴,讓我?guī)兔φ乙恍?面試題?資料,于是我翻遍了收藏的 5T 資料后,匯總整理出來,可以說是程序員面試必備!所有資料都整理到網(wǎng)盤了,歡迎下載!


          點(diǎn)擊??卡片,關(guān)注后回復(fù)【面試題】即可獲取
          瀏覽 66
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  免费黄色小网站 | 欧美激情视频网站 | 操逼操逼黄片 | 亚洲日本黄色视频 | 欧美黄色大片免费在线观看 |