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

 

深入的介紹,待續。。。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM