【问题标题】:Case-insensitive REPLACE in MySQL?MySQL中不区分大小写的替换?
【发布时间】:2011-08-05 02:11:33
【问题描述】:

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'
+-----------------------------+

【问题讨论】:

    标签: mysql replace


    【解决方案1】:

    如果replace(lower()) 不起作用,您需要创建another function.

    【讨论】:

    • 我需要保留原始字符串的未替换余数的大小写,所以没有。
    • 更新 repSchedule SET Email=REPLACE (LOWER(email), '@xyz.com','@xxyyzz.co.uk')
    【解决方案2】:

    我的 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

    【讨论】:

    • 在这种特殊情况下,'where ...'部分并不是绝对必要的,因为该函数只会替换找到匹配项的位置,但我认为很高兴注意到 regexp 可以也用于 where 条件。顺便说一句,纯mysql支持where条件中的正则表达式,但不支持regexp_replace。
    【解决方案3】:

    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

    【讨论】:

      【解决方案4】:

      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】:

        我选择了http://pento.net/2009/02/15/case-insensitive-replace-for-mysql/(在 fvox 的回答中),它使用区分大小写的替换执行不区分大小写的搜索,并且不更改搜索字符串中其他地方不受影响的字符的大小写。

        注意同一页面下方的评论指出 CHAR(255) 应更改为 VARCHAR(255) - 这似乎对我来说也是必需的。

        【讨论】:

          【解决方案6】:

          在前面的答案和 pento.net 链接中,LOCATE() 的参数是小写的。

          这是一种资源浪费,因为 LOCATE 默认不区分大小写:

          mysql> select locate('el', 'HELLo');
          +-----------------------+
          | locate('el', 'HELLo') |
          +-----------------------+
          |                     2 |
          +-----------------------+
          

          你可以替换

          WHILE Locate( LCASE(REPLACE_THIS), LCASE(REPLACE_WHERE), last_occurency ) &gt; 0 DO

          WHILE Locate(REPLACE_THIS, REPLACE_WHERE, last_occurency ) &gt; 0 DO

          等等

          【讨论】:

            【解决方案7】:

            如果出现“特殊”字符,则会出现意外行为:

            SELECT case_insensitive_replace('A', 'Ã', 'a')
            

            给予

            a
            

            这是出乎意料的......因为我们只想替换Ã不是A

            更奇怪的是:

            SELECT LOCATE('Ã', 'A');
            

            给予

            0
            

            哪个是正确的结果...似乎与存储过程的参数编码有关...

            【讨论】:

              【解决方案8】:

              我喜欢在需要替换时使用我创建的搜索和替换功能,而不用担心原始字符串或搜索字符串的大小写。如果您在不更改传入字符串的情况下传入空/空搜索字符串或空替换字符串,则此例程会迅速退出。我还添加了一个安全倒计时,以防万一搜索不断循环。这样我们就不会永远陷入循环。如果您认为起始编号太低,请更改起始编号。

              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//
              

              【讨论】:

                猜你喜欢
                • 2014-02-16
                • 2010-10-29
                • 2018-01-06
                • 1970-01-01
                • 2013-10-19
                • 2017-07-19
                • 2011-12-22
                • 1970-01-01
                相关资源
                最近更新 更多