2016-09-13 3 views
0

The **compare-on-binary way** is **NOT semantically-correct** Строгое строковое сравнение MySQL семантически правильно?

Например, если вы хотите сделать строгих сравнение строк с различными закодированными строками, ошибка Сравнения-на-бинарным Пути выходит. Следующий тест показывает, почему:

В этом случае, я хочу, чтобы заменить строку '北京 ' (с tailling пространства) в поле 城市 в строку '北京111', но сохранить строку '北京' без изменений, поэтому я записать следующее SQL :

SELECT CASE WHEN BINARY `城市` = BINARY '北京 ' THEN '北京111' ELSE `城市` END 
FROM `中文测试表1` 
GROUP BY BINARY CASE WHEN BINARY `城市` = BINARY '北京 ' THEN '北京111' ELSE `城市` END 

Основополагающее определение таблицы и данные (кодирование сеанса выставиться в 'utf8mb4'):

CREATE TABLE `中文测试表1` (
    `城市` varchar(50) CHARACTER SET gbk DEFAULT NULL, 
    `销量` int(11) DEFAULT NULL 
) ENGINE=InnoDB; 

INSERT INTO `中文测试表1` VALUES ('杭州', '111'); 
INSERT INTO `中文测试表1` VALUES ('北京', '345'); 
INSERT INTO `中文测试表1` VALUES ('北京 ', '123'); 

а что произошло на самом деле является то, что Strin g '北京 ' не заменяется на '北京111' и по-прежнему сохраняет то, что было в результирующем наборе.

Причина заключается в том, строке буквального '北京 ' кодируются с использованием utf8mb4 (которая решается сессией) и значения строки '北京 ' из поля 城市 кодируются с использованием GBK (которая решается определением таблицы), и когда они преобразованные в двоичные, они не совпадают с каждым байтом, но две строки действительно семантически равны каждому символу (независимо от того, какой метод базового кодирования используется).

Итак, что такое семантически правильный способ строгого сравнения строк в MySQL?

ответ

0

См. Функцию TRIM() для удаления пробелов из начала и конца строк.

Преобразование между gbk и utf8mb4 оставляет вас во власти таблиц преобразования; вы можете (или не можете) получить необходимую транслитерацию.

'北京' является НЕХОМ E58C97 E4BAAC для utf8/utf8mb '北京 ' является НЕХОМ E58C97 E4BAAC 20 для utf8/utf8mb4 - как найдено в запросе
'北京' является НЕХ B1B1 BEA9 для GBK
'北京 ' является НЕХОМ B1B1 BEA9 20 для GBK - как найден в таблица

Когда вы говорите SELECT ... BINARY '北京 ' ..., кодировка для строки основывается на соединении, а не на кодировке столбца. Так что это utf8mb4.

Вместо ... WHEN BINARY 城市 = BINARY '北京 ' THEN ..., сделайте одно из них:

план А, Пусть преобразование происходит автоматически: ... WHEN 城市 = '北京 ' THEN ...

Plan B, Явное преобразование: ... WHEN 城市 = CONVERT('北京 ' USING gbk) THEN ...

Plan C, используйте HEX: ... WHEN HEX(城市) = HEX(CONVERT('北京 ' USING gbk)) THEN ...

Plan D, поближе к вашей цели: ... WHEN BINARY 城市 = BINARY(CONVERT('北京 ' USING gbk)) THEN ...

Существуют и другие способы использования COLLATE utf8_bin, COLLATE gbk_bin и т. Д.

+0

Я думаю, что план D, который вы упомянули выше, близок к моему намерению, но он требует знать, что указанное поле в базе данных закодировано с использованием gbk, которое я должен предварительно запросить, прежде чем я создам и отправлю целевой запрос. поэтому я не думаю, что это достаточно хороший способ сделать это ... еще, THX за вашу помощь :) – luochen1990

Смежные вопросы