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/
編集: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
「特殊」文字の場合、予期しない動作があります。
SELECT case_insensitive_replace('A', 'Ã', 'a')
与える
a
これは予期しないことです... weを置き換えるだけなので、
さらに奇妙なのは:
SELECT LOCATE('Ã', 'A');
与える
0
これは正しい結果です...ストアドプロシージャのパラメーターのエンコードに関係しているようです...
私は http://pento.net/2009/02/15/case-insensitive-replace-for-mysql/ (fvoxの回答)を使用しました。検索文字列の他の場所で影響を受けない文字の大文字と小文字を変更せずに。
N.B.同じページのさらに下にあるコメントで、CHAR(255)をVARCHAR(255)に変更する必要があることを示しています。これも私には必要なようです。
Luistの回答をこのように変更すると、針をケースの異なるバージョンの針に置き換えることができます(2本の線が変わります)。
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
等.