2011-04-13 113 views
21

除了使用REPLACE命令之外,MySQL在默認排序規則下運行幾乎所有的字符串比較。我有一個不區分大小寫的排序規則,需要運行不區分大小寫的REPLACE。有什麼辦法可以強制REPLACE使用當前的排序規則,而不是總是進行區分大小寫的比較嗎?我願意升級我的MySQL(當前運行5.1),以獲得額外的功能...MySQL中不區分大小寫的REPLACE?

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

回答

16

如果replace(lower())不工作,你需要創建another function.

+6

我需要保留原始字符串的非替換剩餘的情況下,所以沒有。 – dkarp 2011-04-13 21:54:52

+0

UPDATE repSchedule SET Email = REPLACE(LOWER(email),'@ xyz.com','@ xxyyzz.co.uk') – zzapper 2015-01-13 18:04:58

+0

鏈接中的函數是我需要的!謝謝! – 2016-02-09 03:54:50

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

0

http://pento.net/2009/02/15/case-insensitive-replace-for-mysql/去(在fvox的答案),其執行與區分大小寫的更換和不改變的情況下,不區分大小寫什麼應該在搜索字符串的其他地方不受影響的字符。

N.B.在同一個頁面下面的註釋指出CHAR(255)應該改爲VARCHAR(255) - 這對我來說似乎也是需要的。

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 ; 
0

在以前的答案,以及pento.net環節,參數LOCATE()是小寫。

這是對資源的浪費,如LOCATE是不區分大小寫的默認:

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

您可以

WHILE Locate(REPLACE_THIS, REPLACE_WHERE, last_occurency) > 0 DO

等替代

WHILE Locate(LCASE(REPLACE_THIS), LCASE(REPLACE_WHERE), last_occurency) > 0 DO

0

在 '特殊' 字符萬一有意外的行爲:

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

給人

a 

這是意外......因爲我們只需要更換一個不

更令人不可思議:

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

0 

這是正確的結果......似乎有編碼做存儲過程的參數...

1

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

+1

在這種特殊情況下,'where ...'部分並不是絕對必要的,因爲該函數只會替換髮現匹配的位置,但我認爲應該注意regexp可以用於* where *條件。順便說一句,正則表達式在*哪裏*條件是支持在普通的MySQL,但不是regexp_replace。 – 2016-04-27 17:15:50