Как преобразовать столбец в ASCII на лету без сохранения, чтобы проверить совпадения с внешней строкой ASCII? - PullRequest
4 голосов
/ 20 ноября 2010

У меня есть функция поиска членов, в которой вы можете задавать части имен, а возвращаемое значение должно быть у всех членов, имеющих хотя бы одно из имени пользователя, имени или фамилии, совпадающих с этим вводом.Проблема здесь состоит в том, что некоторые имена имеют «странные» символы, такие как é в Renée, и пользователь не хочет вводить странные символы, но обычную замену ASCII e.

В PHP Iпреобразуйте входную строку в ASCII, используя iconv (на тот случай, если кто-то введет странные символы).Однако в базе данных я также должен преобразовать странные символы в ASCII (очевидно) для соответствия строк.

Я попробовал следующее:

SELECT
  CONVERT(_latin1'Renée' USING ascii) t1, 
  CAST(_latin1'Renée' AS CHAR CHARACTER SET ASCII) t2;

(это две попытки.) Оба донне работаетОба имеют Ren?e в качестве вывода.Знак вопроса должен быть e.Ничего страшного, если он выдает Ren?ee, поскольку я могу просто удалить все знаки вопроса после преобразования.

Как вы можете себе представить, столбцы, которые я хочу запросить, имеют кодировку Latin1.

Спасибо.

Ответы [ 4 ]

7 голосов
/ 24 декабря 2010

Вам не нужно ничего конвертировать. Ваше требование - сравнить две строки и спросить, равны ли они, игнорируя акценты; сервер базы данных может использовать для этого сопоставление :

В сопоставлениях, не относящихся к УЦА, один на один отображение из кода символа в вес. В MySQL такие сопоставления случаются нечувствительный и нечувствительный к акценту. utf8_general_ci является примером: «а», «А», «А» и «А» имеют разные коды символов, но все имеют вес 0x0041 и сравните как равное.

mysql> SET NAMES 'utf8' COLLATE 'utf8_general_ci';
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT 'a' = 'A', 'a' = 'À', 'a' = 'á';
+-----------+-----------+-----------+
| 'a' = 'A' | 'a' = 'À' | 'a' = 'á' |
+-----------+-----------+-----------+
|         1 |         1 |         1 |
+-----------+-----------+-----------+
1 row in set (0.06 sec)
5 голосов
/ 26 декабря 2010

Прежде всего, это должно работать следующим образом:

SELECT * FROM `test` WHERE `name` COLLATE utf8_general_ci LIKE '%renee%';

Где таблица test:

+-----+--------+
| id  | name   |
+-----+--------+
|  1  | Renée  |
|  2  | Renêe  |
|  3  | Renee  |
+-----+--------+

Какая у вас версия MySQL и как вы пытаетесь соответствовать?


Одним из других возможных решений является транслитерация .

Похожие: PHP транслитерация

Транслитерация входных данных не должна быть проблемой, но транслитерация значений из постоянной памяти (например, в дБ) в реальном времени во время поиска может быть невозможной. Таким образом, вы можете добавить еще три поля, такие как: username_slug, firstname_slug и lastname_slug. При вставке / изменении записи, установите значения слагов соответственно. И при поиске ищите транслитерированный ввод по полям этого слага.

+------+----------+---------------+----------+---------------+ ...
| id   | username | username_slug | lastname | lastname_slug | ...
+------+----------+---------------+----------+---------------+ ...
|    1 | Renée    |    renee      | La Niña  | la-nina       | ...
|    2 | Renêe    |    renee      | ...      | ...           | ...
|    3 | Renee    |    renee      | ...      | ...           | ...
+------+----------+---------------+----------+---------------+ ...

Поиск "renee" или "renèe" будет соответствовать всем записям.

В качестве побочного эффекта вы можете использовать эти поля для создания ссылок SEF (дружественных для поисковых систем), поэтому они имеют имена ..._slug, например. example.com/users/renee. Конечно, в этом случае вам следует проверить уникальность поля слагов.

3 голосов
/ 25 декабря 2010

@ vincebowdren ответ выше работает, я просто добавляю это как ответ для форматирования:

CREATE TABLE `members` (
  `id` int(11) DEFAULT NULL,
  `lastname` varchar(20) COLLATE utf8_unicode_ci DEFAULT NULL
);
insert into members values (1, 'test6ë');
select id from members where lastname like 'test6e%';

Урожайность

+------+
| id   |
+------+
|    1 |
+------+

И используя Latin1,

set names latin1;
CREATE TABLE `members2` (
  `id` int(11) DEFAULT NULL,
  `lastname` varchar(20) CHARACTER SET latin1 DEFAULT NULL
);
insert into members2 values (1, 'Renée');
select id from members2 where lastname like '%Renee%';

даст:

+------+
| id   |
+------+
|    1 |
+------+

Конечно, OP должен иметь ту же кодировку в приложении (PHP), соединение (MySQL в Linux используется по умолчанию для latin1 в 5.0, но по умолчанию UTF8 в 5.1), а в типе данных поля должно быть меньше неизвестных , Об остальном заботятся сборники.

РЕДАКТИРОВАТЬ: Я написал должен , чтобы иметь лучший контроль над всем, но следующее также работает:

set names latin1;
select id from members where lastname like 'test6ë%';

Поскольку, как только кодировка соединения установлена, MySQL выполняет преобразование внутри. В этом случае он преобразует каким-либо образом преобразование и сравнивает строку UTF8 (из БД) с латиницей 1 (из запроса).

РЕДАКТИРОВАТЬ 2: Некоторый скептицизм требует от меня привести еще более убедительный пример:

Учитывая приведенные выше утверждения, вот что я сделал больше. Убедитесь, что терминал находится в UTF8.

set names utf8;
insert into members values (5, 'Renée'), (6, 'Renêe'), (7, 'Renèe');
select members.id, members.lastname, members2.id, members2.lastname
from members inner join members2 using (lastname);

Помните, что members в utf8 и members2 в latin1.

+------+----------+------+----------+
| id   | lastname | id   | lastname |
+------+----------+------+----------+
|    5 | Renée    |    1 | Renée    |
|    6 | Renêe    |    1 | Renée    |
|    7 | Renèe    |    1 | Renée    |
+------+----------+------+----------+

, что подтверждается правильными настройками, сортировка делает работу за вас.

3 голосов
/ 20 ноября 2010

Оператор CAST() в контексте кодировки символов переводит из одного метода хранения символов в другой - он не меняет фактические символы, то есть то, что вам нужно.Символ é - это то, чем он является в любом наборе символов, это не e.Вам необходимо преобразовать акцентированные символы в неакцентированные символы, что является другой проблемой и задавалось несколько раз ранее ( нормализация акцентированных символов в запросах MySQL ).

Я не уверенесли есть способ сделать это непосредственно в MySQL, если не считать таблицы перевода и прохождения по буквам.Скорее всего, было бы проще написать сценарий PHP, чтобы пройтись по базе данных и сделать переводы.

...