记一次数据库空格问题

又是公司大佬给排查解决了这个问题.. 😆 😆 😆 感激....

问题现象

mysql数据

id name
1782 I See You

需求

后台查询"I see You"的时候匹配到这条数据

sql

select * from table where name like "%I See You%"; 

按照常理来说,,这个sql是没有问题的..但是却搜索不到

改变sql

select * from table where name like "%I%%See%%You%"; 

这样就能搜索到

结论

  • 我们自己打的" "(空格)在mysql中并不是空格.这里暂时下一个定论..他并不是空格
  • I See You 并不等于 数据库的 I See You

debug

判断字符是否一样

return var_dump("I See You" == $song->name);

结果是false

打印二进制文件

就是把自己的I See You和打印出来的I See You放到一个文件中

xxd /tmp/a.txt
0000000: 7374 7269 6e67 2831 3129 2022 49c2 a053  string(11) "I..S
0000010: 6565 c2a0 596f 7522 0a73 7472 696e 6728  ee..You".string(
0000020: 3131 2920 2249 c2a0 5365 65c2 a059 6f75  11) "I..See..You
0000030: 220a 7374 7269 6e67 2839 2920 2249 2053  ".string(9) "I S
0000040: 6565 2059 6f75 220a                      ee You".

结果发现数据库是 .. 自己打的却是

JavaScript encode 空格

encodeURIComponent(" ")
"%C2%A0"

google 搜索 "%C2%A0"

搜索到关键字 non breaking space

发现转码网站

搜索mysql 如何替换non breaking space

这里发现 stackoverflow

发现sql
update songs set name = replace(name, UNHEX('C2A0'),' ') WHERE id=1782

修复问题

正则匹配

因为正则只能匹配只能复制那个空格符号, 来匹配.. 但是我个人觉得这个办法不如mysql来的好.. 因为多个项目弄的话, 很麻烦 要多个项目改..

而且,如果有人不小心 自己手动删除了那个空格.. 同时又自己打了个上去... 就很悲剧了.. 这时候就匹配不到了

$b = preg_replace('/[\s ]+/','x',$name);
var_dump($b);

mysql update

// 查询到有问题的歌曲
select * from songs where name like concat('%',UNHEX('C2A0'),'%')

// 修复歌曲
update songs set name = replace(name, UNHEX('C2A0'),' ') WHERE id=song_id

Laravel 中sql写法

查询

rep()->song->m()->where('id', '>', $latestNameId)
        ->whereRaw("name like concat('%',UNHEX('C2A0'),'%')")
        ->select(['id', 'name', 'author'])
        ->get();

update

DB::update("update songs set name = replace(name, UNHEX('C2A0'),' ') WHERE id=:song_id",['song_id' => $songId]);