Ответ 1
Если replace(lower())
не работает, вам нужно будет создать другую функцию.
MySQL выполняет почти все сопоставления строк при сопоставлении по умолчанию... кроме команды REPLACE
. У меня есть учетная запись, не учитывающая регистр, и вам необходимо запустить без учета регистра REPLACE
. Есть ли способ заставить REPLACE
использовать текущую сортировку, а не всегда делать схожие с регистром сравнения? Я хочу обновить MySQL (в настоящее время работает 5.1), чтобы получить добавленную функциональность...
mysql> charset utf8 collation utf8_unicode_ci;
Charset changed
mysql> select 'abc' like '%B%';
+------------------+
| 'abc' like '%B%' |
+------------------+
| 1 |
+------------------+
mysql> select replace('aAbBcC', 'a', 'f');
+-----------------------------+
| replace('aAbBcC', 'a', 'f') |
+-----------------------------+
| fAbBcC | <--- *NOT* 'ffbBcC'
+-----------------------------+
Если replace(lower())
не работает, вам нужно будет создать другую функцию.
Мои 2 цента.
Поскольку многие люди обновили MySQL до MariaDB, им будет доступна новая функция REGEXP_REPLACE
. Используйте его как обычную замену, но шаблон является регулярным выражением.
Это рабочий пример:
UPDATE 'myTable'
SET 'myField' = REGEXP_REPLACE('myField', '(?i)my insensitive string', 'new string')
WHERE 'myField' REGEXP '(?i)my insensitive string'
Опция (?i)
делает все последующие совпадения нечувствительными к регистру (если поместить в начало шаблона, как у меня, то все это нечувствительно).
Смотрите здесь для получения дополнительной информации: https://mariadb.com/kb/en/mariadb/pcre/
Изменение: regexp_replace
с MySQL 8.0, теперь вы также можете использовать функцию regexp_replace
, см. Документацию: https://dev.mysql.com/doc/refman/8.0/en/regexp.html.
Альтернативная функция для одного произнесенного fvox.
DELIMITER |
CREATE FUNCTION case_insensitive_replace ( REPLACE_WHERE text, REPLACE_THIS text, REPLACE_WITH text )
RETURNS text
DETERMINISTIC
BEGIN
DECLARE last_occurency int DEFAULT '1';
IF LCASE(REPLACE_THIS) = LCASE(REPLACE_WITH) OR LENGTH(REPLACE_THIS) < 1 THEN
RETURN REPLACE_WHERE;
END IF;
WHILE Locate( LCASE(REPLACE_THIS), LCASE(REPLACE_WHERE), last_occurency ) > 0 DO
BEGIN
SET last_occurency = Locate(LCASE(REPLACE_THIS), LCASE(REPLACE_WHERE));
SET REPLACE_WHERE = Insert( REPLACE_WHERE, last_occurency, LENGTH(REPLACE_THIS), REPLACE_WITH);
SET last_occurency = last_occurency + LENGTH(REPLACE_WITH);
END;
END WHILE;
RETURN REPLACE_WHERE;
END;
|
DELIMITER ;
Малый тест:
SET @str = BINARY 'New York';
SELECT case_insensitive_replace(@str, 'y', 'K');
Ответы: New Kork
Я пошел с http://pento.net/2009/02/15/case-insensitive-replace-for-mysql/ (в ответе fvox), который выполняет поиск без учета регистра с учетом чувствительности к регистру и не меняя случая того, что должны быть незатронутыми символами в другом месте в искомой строке.
N.B. комментарий далее по той же странице, в котором указано, что CHAR (255) следует изменить на VARCHAR (255) - это, как мне казалось, тоже необходимо для меня.
Эта модификация ответа Луиста позволяет заменить иглу другим вариантом иглы (две строки меняются).
DELIMITER |
CREATE FUNCTION case_insensitive_replace ( REPLACE_WHERE text, REPLACE_THIS text, REPLACE_WITH text )
RETURNS text
DETERMINISTIC
BEGIN
DECLARE last_occurency int DEFAULT '1';
IF LENGTH(REPLACE_THIS) < 1 THEN
RETURN REPLACE_WHERE;
END IF;
WHILE Locate( LCASE(REPLACE_THIS), LCASE(REPLACE_WHERE), last_occurency ) > 0 DO
BEGIN
SET last_occurency = Locate(LCASE(REPLACE_THIS), LCASE(REPLACE_WHERE), last_occurency);
SET REPLACE_WHERE = Insert( REPLACE_WHERE, last_occurency, LENGTH(REPLACE_THIS), REPLACE_WITH);
SET last_occurency = last_occurency + LENGTH(REPLACE_WITH);
END;
END WHILE;
RETURN REPLACE_WHERE;
END;
|
DELIMITER ;
В предыдущих ответах и в ссылке pento.net аргументы LOCATE()
имеют нижний регистр.
Это пустая трата ресурсов, поскольку по умолчанию LOCATE не учитывает регистр:
mysql> select locate('el', 'HELLo');
+-----------------------+
| locate('el', 'HELLo') |
+-----------------------+
| 2 |
+-----------------------+
Вы можете заменить
WHILE Locate( LCASE(REPLACE_THIS), LCASE(REPLACE_WHERE), last_occurency ) > 0 DO
с
WHILE Locate(REPLACE_THIS, REPLACE_WHERE, last_occurency ) > 0 DO
и др.
В случае "специальных" символов возникает непредвиденное поведение:
SELECT case_insensitive_replace('A', 'Ã', 'a')
дает
a
Это неожиданно... поскольку мы хотим заменить только Ã not A
Что еще более странно:
SELECT LOCATE('Ã', 'A');
дает
0
Какой правильный результат... похоже, связан с кодированием параметров хранимой процедуры...