Mysql通过一个限制条件,查出多条不同的记录

表1和表2是不同数据库中的同名table,但是发现表1中的查询和表2中的查询有区别,(事实是表1的查询是对的。)

表1的查询结果
mysql> select  * from slot_value where slot_type_id='09FDBC8081294EF09D65F909E7FD9DE3' and slot_value='a bout de souffle'  ;
+---------+----------------------------------+-------------------+
| id      | slot_type_id                     | slot_value        |
+---------+----------------------------------+-------------------+
| 2316211 | 09FDBC8081294EF09D65F909E7FD9DE3 | a bout de souffle |
+---------+----------------------------------+-------------------+
1 row in set (0.02 sec)
mysql> select  * from slot_value where slot_type_id='09FDBC8081294EF09D65F909E7FD9DE3' and slot_value='à bout de souffle'  ;;
+---------+----------------------------------+--------------------+
| id      | slot_type_id                     | slot_value         |
+---------+----------------------------------+--------------------+
| 2316212 | 09FDBC8081294EF09D65F909E7FD9DE3 | à bout de souffle  |
+---------+----------------------------------+--------------------+
1 row in set (0.05 sec)

表2的查询结果
mysql> select  * from back_brace.slot_value where slot_type_id='09FDBC8081294EF09D65F909E7FD9DE3' and slot_value='a bout de souffle'  ;
+---------+----------------------------------+--------------------+
| id      | slot_type_id                     | slot_value         |
+---------+----------------------------------+--------------------+
| 1109666 | 09FDBC8081294EF09D65F909E7FD9DE3 | a bout de souffle  |
| 1109667 | 09FDBC8081294EF09D65F909E7FD9DE3 | à bout de souffle  |
+---------+----------------------------------+--------------------+
2 rows in set (2.65 sec)

囧了,竟然遇到上面的情况。。。。。。
但是通过查看对应的编码,是不同的:
mysql> select hex('a')
    -> ;
+----------+
| hex('a') |
+----------+
| 61       |
+----------+
1 row in set (0.01 sec)

mysql> select hex('à');
+-----------+
| hex('à')  |
+-----------+
| C3A0      |
+-----------+
1 row in set (0.01 sec)

接下来怀疑的是,表结构是否相同?
表1:
slot_value | CREATE TABLE `slot_value` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `slot_type_id` varchar(36) COLLATE utf8_bin NOT NULL COMMENT 'slot类型id',
  `slot_value` varchar(255) COLLATE utf8_bin NOT NULL COMMENT 'slot值',
  PRIMARY KEY (`id`),
  UNIQUE KEY `slot_value_uniq_index` (`slot_type_id`,`slot_value`,`out_value`),
  KEY `slot_type_id` (`slot_type_id`),
  KEY `slot_value_type_index` (`type`),
  KEY `slot_value_type_id_index` (`slot_type_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3762859 DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='保存slot类型对应的值信息表,一个slot类型可以有多个slot_value值' |

表2:
| slot_value | CREATE TABLE `slot_value` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `slot_type_id` varchar(36) NOT NULL COMMENT 'slot类型id',
  `slot_value` varchar(255) NOT NULL COMMENT 'slot值',
  PRIMARY KEY (`id`),
  KEY `index_slot_type_id` (`slot_type_id`)
) ENGINE=InnoDB AUTO_INCREMENT=2309045 DEFAULT CHARSET=utf8 COMMENT='保存slot类型对应的值信息表,一个slot类型可以有多个slot_value值' 

发现表1和表2的不同之处,在于建表语句的稍微不同,表1的建表语句中有 COLLATE=utf8_bin,表2没有这句。
将表2修改表结构,增加表1中有的COLLATE=utf8_bin,修改的方法如下
alter table slot_value CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin;
修改后表结构如下:
slot_value | CREATE TABLE `slot_value` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `slot_type_id` varchar(36) COLLATE utf8_bin NOT NULL COMMENT 'slot类型id',
  `slot_value` varchar(255) COLLATE utf8_bin NOT NULL COMMENT 'slot值',
  PRIMARY KEY (`id`),
  KEY `index_slot_type_id` (`slot_type_id`)
) ENGINE=InnoDB AUTO_INCREMENT=2309045 DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='保存slot类型对应的值信息表,一个slot类型可以有多个slot_value值'   

再在表2上执行查询语句:
mysql> select * from slot_value where slot_type_id='09FDBC8081294EF09D65F909E7FD9DE3' and slot_value='à bout de souffle'; 
+---------+----------------------------------+--------------------+
| id      | slot_type_id                     | slot_value         |
+---------+----------------------------------+--------------------+
| 1109667 | 09FDBC8081294EF09D65F909E7FD9DE3 | à bout de souffle  |
+---------+----------------------------------+--------------------+
1 row in set (2.07 sec)

mysql> select * from slot_value where slot_type_id='09FDBC8081294EF09D65F909E7FD9DE3' and slot_value='a bout de souffle'; 
+---------+----------------------------------+-------------------+
| id      | slot_type_id                     | slot_value        |
+---------+----------------------------------+-------------------+
| 1109666 | 09FDBC8081294EF09D65F909E7FD9DE3 | a bout de souffle |
+---------+----------------------------------+-------------------+
1 row in set (2.34 sec)

完美解决问题。。。
但是为什么呢?

原来MySQL按照下面的方式选择表字符集和 校对规则:
如果指定了CHARACTER SET X和COLLATE Y,那么采用CHARACTER SET X和COLLATE Y。
如果指定了CHARACTER SET X而没有指定COLLATE Y,那么采用CHARACTER SET X和CHARACTER SET X的默认校对规则。
否则,采用服务器字符集和服务器校对规则。
而我们在建表的时候指定了character set,所以它永远是采用对应的默认的校对规则。
当然我们其实也没必要重建表格,只需要alter table db_allot CONVERT TO CHARACTER SET latin1 COLLATE latin1_bin这样转换即可。
另外建议collation都尽量采用字符集相应的bin类型的校对规则,这样不容易出错。

此外遇到这种情况,不用逐个改字段属性,而只要表格级别的collation就行了。
(对MySQL数据库中的varchar字段有效)


参考文档《MySQL 的 collation》:http://blog.csdn.net/xfsnow/article/details/2885948

深入的介绍,待续。。。

原文地址:https://www.cnblogs.com/zhzhang/p/6895636.html