Case Insensitive REPLACE for MySQL

Is there a case insensitive Replace for MySQL?

I'm trying to replace a user's old username with their new one within a paragraph text.

$targetuserold = "@".$mynewusername;
$targetusernew = "@".$newusername;

$sql = "
    UPDATE timeline 
    SET message = Replace(message,'".$targetuserold."', '".$targetusernew."')
";

$result = mysql_query($sql);

This is missing the instances where the old username is a different case. Example: replacing "Hank" with "Jack" in all the rows in my database will leave behind instances of "hank".

Asked By: Tom
||

Answer #1:

Here it is:

DELIMITER $$

DROP FUNCTION IF EXISTS `replace_ci`$$
CREATE FUNCTION `replace_ci` ( str TEXT,needle CHAR(255),str_rep CHAR(255))
    RETURNS TEXT
    DETERMINISTIC
    BEGIN
        DECLARE return_str TEXT DEFAULT '';
        DECLARE lower_str TEXT;
        DECLARE lower_needle TEXT;
        DECLARE pos INT DEFAULT 1;
        DECLARE old_pos INT DEFAULT 1;

        SELECT lower(str) INTO lower_str;
        SELECT lower(needle) INTO lower_needle;
        SELECT locate(lower_needle, lower_str, pos) INTO pos;
        WHILE pos > 0 DO
            SELECT concat(return_str, substr(str, old_pos, pos-old_pos), str_rep) INTO return_str;
            SELECT pos + char_length(needle) INTO pos;
            SELECT pos INTO old_pos;
            SELECT locate(lower_needle, lower_str, pos) INTO pos;
        END WHILE;
        SELECT concat(return_str, substr(str, old_pos, char_length(str))) INTO return_str;
        RETURN return_str;
END$$

DELIMITER ;

Usage:

$sql = "
    UPDATE timeline 
    SET message = replace_ci(message,'".$targetuserold."', '".$targetusernew."')
";
Answered By: Yair Nevet

Answer #2:

An easier way that works without any stored function:

SELECT message,
       substring(comments,position(lower('".$targetuserold."') in message) ) AS oldval
  FROM timeline
 WHERE message LIKE '%".$targetuserold."%'

gives you the exact, case sensitive spellings of the username in all messages. As you seem to run that from a PHP script, you could use that to collect the spellings together with the corresponding IDs, and then run a simple REPLACE(message,'".$oldval.",'".$targetusernew."') on that. Or use the above as sub-select:

UPDATE timeline 
    SET message = REPLACE(
                   message,
                   (SELECT substring(comments,position(lower('".$targetuserold."') in message))),
                   '".$targetusernew."'
                  )

Works like a charm here.

Credits given to this article, where I got the idea from.

Answered By: Izzy

Answer #3:

My solution ultimately was that I cannot do a case insensitive Replace.

However, I did find a workaround.

I was trying to have a feature where a user can change their username. The system would then need to update wherever @oldusername was found in all the messages in the database.

The problem was... people wouldn't type other people's usernames in the correct case that it is found in the members table. So when the user would change their username, it wouldn't catch those instances of @oldSeRNAmE because of it not matching the case of the real format of the oldusername.

I don't have permission with my GoDaddy shared server to do this with a customized SQL function, so I had to find a different way.

My solution: Upon inserting new messages into the database, whenever a username is found in the new message, I have an UPDATE statement at that point to replace the username they typed with the correct formatted case that is found in the members table. That way, if that person ever wants to change their username in the future, all the instances of that username in the database will all be the same exact formatted case. Problem solved.

Answered By: Tom
The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 .



# More Articles