2011-04-13 32 views
21

MySQL ejecuta prácticamente todas las comparaciones de cadenas en la intercalación predeterminada ... excepto el comando REPLACE. Tengo una intercalación insensible a mayúsculas y minúsculas y necesito ejecutar un REPLACE insensible a mayúsculas y minúsculas. ¿Hay alguna forma de forzar REPLACE para usar la intercalación actual en lugar de hacer siempre comparaciones de mayúsculas y minúsculas? Estoy dispuesto a actualizar mi MySQL (actualmente en ejecución 5.1) para obtener la funcionalidad añadida ...Insensible a mayúsculas ¿REEMPLAZAR en MySQL?

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

Respuesta

16

Si replace(lower()) no funciona, tendrá que crear another function.

+6

I necesidad de preservar el caso de que el resto no sustituido de la cadena original, por lo que no. – dkarp

+0

UPDATE repSchedule SET Email = REPLACE (INFERIOR (correo electrónico), '@ xyz.com', '@ xxyyzz.co.uk') – zzapper

+0

¡La función en el enlace es lo que necesitaba! ¡Gracias! –

4

función alternativa a uno hablada por 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 ; 

pequeña prueba:

SET @str = BINARY 'New York'; 
SELECT case_insensitive_replace(@str, 'y', 'K'); 

Respuestas: New Kork

0

Fui con http://pento.net/2009/02/15/case-insensitive-replace-for-mysql/ (en la respuesta de fvox) que realiza la búsqueda que ignore con el reemplazo de mayúsculas y minúsculas y sin cambiar el caso de lo deberían ser caracteres no afectados en cualquier parte de la cadena buscada.

N. B. el comentario más abajo en la misma página que indica que CHAR (255) debería cambiarse a VARCHAR (255) - esto también parecía ser necesario para mí.

0

Esta modificación de la respuesta de Luist permite reemplazar la aguja con una versión con carcasa diferente de la aguja (dos líneas cambian).

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

En las respuestas anteriores, y el enlace pento.net, los argumentos a LOCATE() son con carcasa inferior.

Esto es un desperdicio de recursos, como LOCALIZAR es sensible a las mayúsculas por defecto:

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

Puede reemplazar

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

con

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

etc.

0

En caso de caracteres 'especiales' no es un comportamiento inesperado:

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

Da

a 

Cuál es inesperado ...ya que sólo desea reemplazar el un no es un

Lo que es aún más extraño:

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

da

0 

¿Cuál es el resultado correcto ... parece que tiene que ver con la codificación de los parámetros del procedimiento almacenado ...

1

Mis 2 centavos.

Dado que muchas personas se han actualizado de MySQL a MariaDB esas personas tendrán disponible una nueva función llamada REGEXP_REPLACE. Úselo como lo haría con un reemplazo normal, pero el patrón es una expresión regular.

Este es un ejemplo de trabajo:

UPDATE `myTable` 
SET `myField` = REGEXP_REPLACE(`myField`, '(?i)my insensitive string', 'new string') 
WHERE `myField` REGEXP '(?i)my insensitive string' 

La opción (?i) hace que todo el caso coincidencias posteriores insensibles (si se pone en el principio del patrón como si tuviera entonces todo es insensible).

Consulte aquí para obtener más información: https://mariadb.com/kb/en/mariadb/pcre/

+1

en este caso particular la parte 'donde ...' no es estrictamente necesaria, ya que la función solo reemplazará cuando se encuentre una coincidencia, pero pensé que sería bueno tener en cuenta que la expresión regular también puede usarse en condiciones * donde * . Por cierto, regexp en * where * conditions es compatible con mysql simple, pero no con regexp_replace. –

Cuestiones relacionadas