MySQL不区分大小写

341 阅读2分钟

标题解释

MySQL数据库在Linux下的内容默认是大小写不区分的

遇到问题

最近在做从第三方获取数据,同步到本地库。
同步的原则很简单:数据存在就更新,不存在则新增。
伪代码:

// 从第三方获取数据列表 list   
List<Dto> list = getListFromThird();

// 循环list,按照某个唯一字段作为key存入map;并将这个唯一字段存入列表
int listSize = list.size();
Map<String, Dto> key2DtoMap = new HashMap(listSize);
List<String> keys = new ArrayList(listSize);
list.forEach( d-> {
	String key = d.getUniqueName();
    key2DtoMap.put(key, d);
    keys.add(key);
});

// 根据唯一字段列表从本地数据库查询
List<Po> poList = getLocalPoList(keys);

// 循环查出的数据,根据唯一字段从map中获取对象,更新旧数据
if(!CollectionUtis.isEmpty(poList)) {
	poList.forEach( po -> {
    	String key = po.getUniqueName();
        Dto dto = key2DtoMap.get(key);
        
        
        // 注意:此处出现了NPE
        po.setXXX(dto.getXXX());	// 注意:此处出现了NPE
        // 注意:此处出现了NPE
        
        
        ...
        update(po);	// 此处单个保存或循环外批量保存都可以
    }) ;
}

// 处理新增数据
...

在循环本地数据,从map中获取的dto为null。
很奇怪吧,map里面保存了第三方所有的唯一key。并且本地的数据是根据key来获取的,为什么会是null。

原因分析

Debug后发现,本地的数据库的key和第三方的key大小写不一致。
例如第三方的key为abc,并存入到map中;根据abc去db查询,查出了aBc。
循环本地数据,根据aBc去map中获取为null(map中的key为abc)。

解决或避免方案

  1. 使用mysql 的BINARY 关键字使搜索区分大小写。
select * from tb_user where BINARY account_name='abc';

优点:不需要改表
缺点:需要写sql,并要加BINARY。无法使用例如mybatis框架(度娘了下,没找到可以自动加BINARY的语句) 2. 建表使用BINARY限制

CREATE TABLE `t_account` (
    `id` BIGINT (20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增id',
    `account_name` VARCHAR (50) BINARY NOT NULL COMMENT '账号名',
    PRIMARY KEY (`id`)
) ENGINE = INNODB DEFAULT CHARSET = utf8 COMMENT = '账号表';
  1. 代码对唯一值新增修改前做校验