当前位置: 首页 > 科技观察

【MYSQL】业务上碰到的SQL问题整理集合

时间:2023-03-18 19:42:55 科技观察

【MYSQL】业务中遇到的SQL问题如何解决这些问题的集合。SELECT查询语句是否不区分大小写?我相信这是一个很常见的问题,造成这个问题的原因主要是表字符集引起的。假设有一个config表结构:FieldTypeAllowNullDefaultValuekeyvarchar(255)Novaluevarchar(255)Noidint(11)No表中数据如下:keyvalueidVERSION1.0.11version2.0.12执行语句For:SELECT`key`,`value`FROMconfigWHERE`key`='version'LIMIT1;预期结果:keyvalueversion2.0.1执行结果:keyvalueVERSION1.0.1为什么会这样?mysql默认匹配字符排序不区分大小写,字段包括varchar、char、text内容。如果你真的想区分大小写,那么在构建或查找表时使用BINARY属性。二进制A和a还是有区别的~~解决方法一:修改sql语句SELECT`key`,`value`FROMconfigWHERE`key`=binary('version')LIMIT1;orSELECT`key`,`value`FROMconfigWHEREbinary`key`='version'LIMIT1;方案二:修改表结构,建表语句CREATETABLE`config`(`key`BINARYvarchar(255)NOTNULL,`value`BINARYvarchar(255)DEFAULTNULL,`id`int(11)NOTNULL,PRIMARYKEY(`id`))ENGINE=InnoDBDEFAULTCHARSET=utf8;修改表语句ALTERTABLE`config`MODIFYCOLUMN`key`varchar(255)BINARYNOTNULL;SELECTIN语句顺序不符合输入时间要求?以config表为例,表中数据:keyvalueidemail295697141@qq.com1usernameI2SQL语句:SELECT`key`,`value`FROM`config`WHERE`key`IN('username','电子邮件');执行结果:keyvalueemail295697141@qq.comusername我明明更喜欢usernameoveremail,但是结果是email优先于用户名。原因是IN查询只负责查询,不负责排序,默认排序是用idasc,所以你得到的结果不符合IN查询。解决方案使用ORDERBYFIELD()使用ORDERBYFIND_IN_SET()SELECT`key`,`value`FROM`config`WHERE`key`IN('username','email')ORDERBYFIELD('key','username','电子邮件');或SELECT`key`,`value`FROM`config`WHERE`key`IN('username','email')ORDERBYFIND_IN_SET(`key`,'username,email');最终执行结果:keyvalueusernamemyemail295697141@qq.com注意:FIND_IN_SET第二个参数strlist逗号之间不能有空格SELECT存储查询生僻汉字,结果是乱码?前提是数据库和表使用utf8字符集。稀有字符如:𠂤INSERTINTO`config`(`key`,`value`,`id`)VALUES('word','𠂤',7);查询SQL:SELECT*FROM`config`WHERE`key`='word'LIMIT1;执行结果:valuekeyidword?????7????这样的话,是不是意味着utf8字符集没有记录这个生僻字呢?mysql支持的utf8编码***,字符长度为3个字节。如果遇到4个字节将插入宽字符,但UTF-8的三个字节除外。可以编码的Unicode字符是0xffff,也就是Unicode中的BasicMultilingualPlane(BMP)。也就是说,任何不在BasicMultitextPlane中的Unicode字符都不能使用Mysql的utf8字符集来存储。包括Emoji表情(Emoji是一种特殊的Unicode编码,常见于ios和android手机),以及很多不常用的汉字,以及任何新的Unicode字符等。引用MySQLUTF8编码下不常见字符插入失败/假死问题的分析解决办法:修改字符集--修改数据库字符集ALTERDATABASEtestCHARACTERSET=utf8mb4;--修改表字符集altertable`config`converttocharactersetutf8mb4;--修改字符characterSetALTERTABLE`config`CHANGECOLUMN`value``value`varchar(12)CHARACTERSETutf8mb4;最后执行sql-setconnectionsockettousecharactersetSETNAMESutf8mb4;-修改表字段字符集ALTERTABLE`config`CHANGECOLUMN`value``value`varchar(12)CHARACTERSETutf8mb4;-updatevalueUPDATE`config`SET`value`='𠂤'WHERE`key`='word';-querySELECT*FROM`config`WHERE`key`='word';执行结果键值id字𠂤7SELECTLOCATE与LIKE不同使用相同然后用config表举例,如果有如下行数据:keyvalueidapp.version1.0.08h5.version1.0.19app.emailtest@gmail.com10h5.emailtest@outlook.com11LIKE语句如果我们想查询命名空间中以app或h5开头的所有配置项,可以使用LIKE语句SELECT`key`,`value`FROM`config`WHERE`key`喜欢'h5.%';执行结果:keyvalueh5.version1.0.1h5.emailtest@outlook.com如果想去掉h5命名空间前缀,可以使用子串函数SELECTsubstring(`key`,length('h5.')+1),`value`FROM`config`WHERE`key`LIKE'h5.%';执行结果:keyvalueversion1.0.1emailtest@outlook.comLIKE匹配所有字符串,h5.%等预查询时间,如果有索引会有一定的优化效果不会进行全表扫描。LOCATE函数LOCATE是查询匹配字符串出现次数的函数执行语句:SELECT`key`,`value`FROM`config`WHERELOCATE('app',`key`)>0;执行结果:keyvalueapp.version1.0.0app.emailtest@gmail.com研究了相关资料,最后觉得LIKE和LOCATE的效率没法比,谁快谁慢。相关文章推荐阅读MySQLLIKEvsLOCATE总结mysql,sql中的知识确实让人觉得博大精深。此时此刻,我只是解决了我遇到的问题,过一段时间我会遇到更多不同的问题,这也是学习sql和计算机的魅力所在。我以后会遇到更多的问题。SQL有很多疑问,会持续更新……欢迎大家收藏点赞!!!