Неразрывный пробел, mysql и Like
Есть таблица A и таблица B, в каждой из них есть колонка name (обе utf8_general_ci). Потребовалось найти соответствие name из A в B при том, что A.name содержит B.name (полностью). Казалось бы, что проще -
SELECT A.name, B.name FROM A,B
WHERE A.name LIKE CONCAT ('%',B.name,'%')
* вариант с условием WHERE POSITION (B.name in A.name) давал меньше соответствий
Интересная ситуация - визуально записи отображаются одинаково.. однако при попытке сравнить их, как при помощи оператора = или LIKE результат получается “различным”. При этом проверка “ручками” в браузере (поиск по CTRL+F) словосочетания считает абсолютно одинаковыми..
Мысли-поиски натолкнули на решение.. поскольку UTF-8 - кодировка “хитрая”, то, раз буквы одинаковые (кстати, использовались символы из набора ASCII), значит различие в пробелах
В UTF-8 есть несколько видов пробелов.. Неразрывный пробел содержит 2 байта - \xC2\xA0, он же CHAR(194) CHAR(160). По смыслу он очень похож на неразрывный пробел в HTML (чтобы слово не переносилось на следующую строку вместо обычного пробела можно ввести ). Поскольку, найденный неразрывный пробел в данном случае скорее мешал, чем приносил пользу, было принято решение заменить его на “обычный”.
Как ввести неразрывный пробел с клавиатуры
Поставить неразрывный пробел в Word (или другой программе) можно при помощи сочетания символов Shift+Ctrl+Пробел. В Word также можно воспользоваться меню “Вставка -> специальный символ-> выбрать из списка неразрывный пробел)
Замена неразрывного пробела
Неразрывный пробел может быть причиной несовпадения одинаковых строк не только в MySQL и других базах данных (MS SQL, Oracle, PqSQL), но и в языках программирования (как в “скриптовых”-интерпретируемых вроде PHP, Ruby, Python, так и в компилируемых)
Заменить неразрывный пробел в MySQL
Для начала, чтобы убедиться, что он присутствует в нужном столбце можно выполнить запрос такого рода:
SELECT name, REPLACE( name, CONCAT( CHAR( 194 ) , CHAR( 160 ) ) , '**' )
FROM `B` WHERE POSITION( CHAR( 194 ) IN name ) >0
Если неразрывные пробелы имеются, заменить их на обычные можно запросом
UPDATE `B` SET name = REPLACE( name, CONCAT( CHAR( 194 ) , CHAR( 160 ) ) , ' ' )
WHERE POSITION( CHAR( 194 ) IN name ) >0;
Возможно, пригодится замена двух подряд идущих пробелов на один
UPDATE `B` SET name = REPLACE( name, ' ', ' ' ) ;
Заменить неразрывный пробел в PHP
$string=str_replace(chr(194).chr(160),'',$string);