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'
+-----------------------------+
答案 0 :(得分:19)
如果replace(lower())
不起作用,您需要创建another function.
答案 1 :(得分:7)
我的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/
编辑:从MySQL 8.0开始,您现在也可以使用regexp_replace
功能,请参阅文档:https://dev.mysql.com/doc/refman/8.0/en/regexp.html
答案 2 :(得分:4)
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
答案 3 :(得分:0)
我选择http://pento.net/2009/02/15/case-insensitive-replace-for-mysql/(在fvox的答案中),使用区分大小写的替换执行不区分大小写的搜索,而不更改搜索字符串中其他位置应该是未受影响的字符的情况。
N.B。在同一页面上的评论进一步说明CHAR(255)应该改为VARCHAR(255) - 这对我来说似乎也是必需的。
答案 4 :(得分:0)
Luist答案的这一修改允许用不同套管的针头替换针头(两条线改变)。
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 ;
答案 5 :(得分:0)
在之前的答案和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
等
答案 6 :(得分:0)
如果是'特殊'字符,则会出现意外行为:
SELECT case_insensitive_replace('A', 'Ã', 'a')
给出
a
这是意料之外的......因为我们只想替换Ã不是A
更奇怪的是:
SELECT LOCATE('Ã', 'A');
给出
0
哪个是正确的结果......似乎与存储过程的参数编码有关...
答案 7 :(得分:0)
我喜欢使用我需要替换时创建的搜索和替换功能,而不必担心原始或搜索字符串的大小写。如果在不更改输入字符串的情况下传入空/空搜索字符串或空替换字符串,则此例程很快就会失败。我还添加了一个安全倒数,以防万一搜索不断循环。这样我们就不会永远陷入循环中。如果您认为起始数字太低,请更改它。
delimiter //
DROP FUNCTION IF EXISTS `replace_nocase`//
CREATE FUNCTION `replace_nocase`(raw text, find_str varchar(1000), replace_str varchar(1000)) RETURNS text
CHARACTER SET utf8
DETERMINISTIC
BEGIN
declare ret text;
declare len int;
declare hit int;
declare safe int;
if find_str is null or find_str='' or replace_str is null then
return raw;
end if;
set safe=10000;
set ret=raw;
set len=length(find_str);
set hit=LOCATE(find_str,ret);
while hit>0 and safe>0 do
set ret=concat(substring(ret,1,hit-1),replace_str,substring(ret,hit+len));
set hit=LOCATE(find_str,ret,hit+1);
set safe=safe-1;
end while;
return ret;
END//