72

I would like to do a find and replace inside an entire database not just a table.

How can I alter the script below to work?

 update [table_name] set [field_name] = replace([field_name],'[string_to_find]','[string_to_replace]');

Do I just use an asterix?

 update * set [field_name] = replace([field_name],'[string_to_find]','[string_to_replace]');
Stephen Ostermiller
  • 23,933
  • 14
  • 88
  • 109
Andy
  • 2,991
  • 9
  • 43
  • 62
  • 1
    I'm not sure if MySQL allows that, but I would highly doubt it does that seems like a major security firestorm waiting to happen. – josh.trow Jan 27 '11 at 22:25
  • hehe right ok, the trouble is i don't know which table has the info and there are a shit load of tables. – Andy Jan 27 '11 at 22:26
  • To find out which tables have the data you could run a whole DB search which will show you which tables have data matching your search criteria. In phpmyadmin go too /phpmyadmin/db_search.php – Lee Woodman Mar 07 '14 at 13:36
  • Possible duplicate of [How to search and replace all instances of a string within a database?](http://stackoverflow.com/questions/836083/how-to-search-and-replace-all-instances-of-a-string-within-a-database) – Steve Chambers Aug 05 '16 at 15:34

12 Answers12

143

sqldump to a text file, find/replace, re-import the sqldump.

Dump the database to a text file
mysqldump -u root -p[root_password] [database_name] > dumpfilename.sql

Restore the database after you have made changes to it.
mysql -u root -p[root_password] [database_name] < dumpfilename.sql

joshhunt
  • 5,197
  • 4
  • 37
  • 60
Dean Rather
  • 31,756
  • 15
  • 66
  • 72
  • 7
    yup, this worked for me as well. May I add the commands to do that here: backup: # mysqldump -u root -p[root_password] [database_name] > dumpfilename.sql restore:# mysql -u root -p[root_password] [database_name] < dumpfilename.sql NOTE the direction of the >...also, there is no space between the -p and the password – DextrousDave Jul 29 '13 at 06:48
  • 9
    Unless you have a heavy DB which is impossible to open on a normal text editor. – MacK Jun 30 '14 at 10:58
  • 5
    If you're on linux you could use sed to do the search replace (or maybe awk... these don't care how big your file is.) – John Hunt Nov 26 '14 at 16:59
  • Nice, quick solution, unless the string being replaced is in a serialized data, in which case, the query will break if the length of the replacer string is different than that of original string. This is because the serialized data also stores the column count of the data inside it, and if the count does not match, it becomes invalid data for the query. – Prashant Jul 06 '15 at 10:42
  • 4
    But this is not useful if database size is 2.04 GB – Ayyaz Zafar Jul 14 '15 at 17:11
  • 2
    Genius :) Mega facepalm moment for me, but of course it can be done like this. Great. Many Thanks. – wzazza Feb 18 '16 at 16:51
  • very helpful and saved my lots of time :) – Bhawna Malhotra Mar 22 '16 at 06:29
  • 2
    **!!!!!!!!!!!!!!! AVOID THAT !!!!!!!!!!!!** You will mess up the site! read the caution in next answers. – T.Todua Jul 16 '16 at 16:13
  • 3
    This is OK procedure **UNLESS** you have some serialized data - e.g. WordPress widgets :) there comes the problem with count-check :) – jave.web Jul 17 '16 at 11:22
  • A note on security. Don't put the password in the command line. Just use the -p parameter and type the password separately. Adding the password to your command history is usually not a good idea. – mostlydev Oct 18 '16 at 14:40
  • What happens with this method if I want to replace, in the database content, the text `CREATE` by `blabla`? It would break the .sql file itself, wouldn't it? – Basj Oct 22 '16 at 09:35
  • 2
    One caveat for WordPress users and other sad souls who have systems that put PHP serialized arrays in text blobs- Do not do this or your PHP serialized arrays will become corrupted and your WP install will break. – 111 Jan 22 '21 at 00:11
  • lol simple but definitely the only correct answer!! – Mattia Rasulo Jan 30 '21 at 14:01
51

Update old URL to new URL in WordPress MySQL Query:

UPDATE wp_options SET option_value = replace(option_value, 'http://olddomain.example', 'http://newdomain.example') WHERE option_name = 'home' OR option_name = 'siteurl';

UPDATE wp_posts SET guid = replace(guid, 'http://olddomain.example','http://newdomain.example');

UPDATE wp_posts SET post_content = replace(post_content, 'http://olddomain.example', 'http://newdomain.example');

UPDATE wp_posts SET post_excerpt = replace(post_excerpt, 'http://olddomain.example', 'http://newdomain.example');

UPDATE wp_postmeta SET meta_value = replace(meta_value, 'http://olddomain.example', 'http://newdomain.example');
Stephen Ostermiller
  • 23,933
  • 14
  • 88
  • 109
Vishnu Sharma
  • 1,357
  • 12
  • 11
  • 5
    Don't forget the _post_excerpt_ column under the _wp_posts_ table: `UPDATE wp_posts SET post_excerpt = replace(post_excerpt, 'http://olddomain.com', 'http://newdomain.com');` – Jonathan Hult Apr 30 '16 at 04:18
7

BE CAREFUL, when replacing with REPLACE command!

why?

because there is a great chance that your database contains serialized data (especially wp_options table), so using just "replace" might break data.

Use recommended serialization: https://puvox.software/tools/wordpress-migrator

T.Todua
  • 53,146
  • 19
  • 236
  • 237
  • Not really a bad answer, you saved me some headache. – Hmmm Apr 19 '17 at 03:35
  • I strongly recommend avoiding such tools in regard to trust issues. However, I tested it with a dummy database and it failed every time. – sybozz Jun 19 '21 at 12:42
6

This strongly implies that your data IS NOT NORMALISED to begin with.

Something like this should work (NB you've not mentioned of your using any other languages - so its written as a MySQL stored procedure)

 create procedure replace_all(find varchar(255), 
        replce varchar(255), 
        indb varcv=char(255))
 DECLARE loopdone INTEGER DEFAULT 0;
 DECLARE currtable varchar(100);
 DECLARE alltables CURSOR FOR SELECT t.tablename, c.column_name 
    FROM information_schema.tables t,
    information_schema.columns c
    WHERE t.table_schema=indb
    AND c.table_schema=indb
    AND t.table_name=c.table_name;

 DECLARE CONTINUE HANDLER FOR NOT FOUND
     SET loopdone = 1;

 OPEN alltables;

 tableloop: LOOP
    FETCH alltables INTO currtable, currcol; 
    IF (loopdone>0) THEN LEAVE LOOP;
    END IF;
         SET stmt=CONCAT('UPDATE ', 
                  indb, '.', currtable, ' SET ',
                  currcol, ' = word_sub(\'', find, 
                  '\','\'', replce, '\') WHERE ',
                  currcol, ' LIKE \'%', find, '%\'');
         PREPARE s1 FROM stmt;
         EXECUTE s1;
         DEALLOCATE PREPARE s1;
     END LOOP;
 END //

I'll leave it to you to work out how to declare the word_sub function.

user229044
  • 232,980
  • 40
  • 330
  • 338
symcbean
  • 47,736
  • 6
  • 59
  • 94
4

Short answer: You can't.

Long answer: You can use the INFORMATION_SCHEMA to get the table definitions and use this to generate the necessary UPDATE statements dynamically. For example you could start with this:

SELECT TABLE_NAME, COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'your_schema'

I'd try to avoid doing this though if at all possible.

Mark Byers
  • 811,555
  • 193
  • 1,581
  • 1,452
2

MySQL Search & Replace Tool

Very useful web-based tool written in PHP which makes it easy to search and replace text strings in a MySQL database.

user1794295
  • 1,839
  • 4
  • 21
  • 19
2

I had the same issue on MySQL. I took the procedure from symcbean and adapted her to my needs.

Mine is only replacing textual values (or any type you put in the SELECT FROM information_schema) so if you have date fields, you will not have an error in execution.

Mind the collate in SET @stmt, it must match you database collation.

I used a template request in a variable with multiple replaces but if you have motivation, you could have done it with one CONCAT().

Anyway, if you have serialized data in your database, don't use this. It will not work unless you replace your string with a string with the same lenght.

Hope it helps someone.

DELIMITER $$

DROP PROCEDURE IF EXISTS replace_all_occurences_in_database$$
CREATE PROCEDURE replace_all_occurences_in_database (find_string varchar(255), replace_string varchar(255))
BEGIN
  DECLARE loop_done integer DEFAULT 0;
  DECLARE current_table varchar(255);
  DECLARE current_column varchar(255);
  DECLARE all_columns CURSOR FOR
  SELECT
    t.table_name,
    c.column_name
  FROM information_schema.tables t,
       information_schema.columns c
  WHERE t.table_schema = DATABASE()
  AND c.table_schema = DATABASE()
  AND t.table_name = c.table_name
  AND c.DATA_TYPE IN('varchar', 'text', 'longtext');

  DECLARE CONTINUE HANDLER FOR NOT FOUND
  SET loop_done = 1;

  OPEN all_columns;

table_loop:
LOOP
  FETCH all_columns INTO current_table, current_column;
  IF (loop_done > 0) THEN
    LEAVE table_loop;
  END IF;
  SET @stmt = 'UPDATE `|table|` SET `|column|` = REPLACE(`|column|`, "|find|", "|replace|") WHERE `|column|` LIKE "%|find|%"' COLLATE `utf8mb4_unicode_ci`;
  SET @stmt = REPLACE(@stmt, '|table|', current_table);
  SET @stmt = REPLACE(@stmt, '|column|', current_column);
  SET @stmt = REPLACE(@stmt, '|find|', find_string);
  SET @stmt = REPLACE(@stmt, '|replace|', replace_string);
  PREPARE s1 FROM @stmt;
  EXECUTE s1;
  DEALLOCATE PREPARE s1;
END LOOP;
END
$$

DELIMITER ;
1

Simple Soltion

UPDATE `table_name`
 SET `field_name` = replace(same_field_name, 'unwanted_text', 'wanted_text')
Jaha Rabari
  • 173
  • 8
1

This isn't possible - you need to carry out an UPDATE for each table individually.

WARNING: DUBIOUS, BUT IT'LL WORK (PROBABLY) SOLUTION FOLLOWS

Alternatively, you could dump the database via mysqldump and simply perform the search/replace on the resultant SQL file. (I'd recommend offlining anything that might touch the database whilst this is in progress, as well as using the --add-drop-table and --extended-insert flags.) However, you'd need to be sure that the search/replace text wasn't going to alter anything other than the data itself (i.e.: that the text you were going to swap out might not occur as a part of SQL syntax) and I'd really try doing the re-insert on an empty test database first.)

John Parker
  • 54,048
  • 11
  • 129
  • 129
1

If you are in phpMyAdmin and you have only a minimal change, you can do this in an easy way.

  • Login to your phpMyAdmin
  • Select the database you need to perform the changes
  • Click on the search option

    enter image description here

You can always select either all the tables or any. Remember to give the search keyword, it will be used as wildcard(%).

  • Now click on Go.
  • This will give you all the tables which have the item you have searched for.

enter image description here

  • Now you can open each table one by one and perform the update A sample query generated may look like the following.

    SELECT * FROM sibeecst_passion.wp_ewwwio_images WHERE (CONVERT(id USING utf8) LIKE '%sibee%' OR CONVERT(path USING utf8) LIKE '%sibee%' OR CONVERT(image_md5 USING utf8) LIKE '%sibee%' OR CONVERT(results USING utf8) LIKE '%sibee%' OR CONVERT(gallery USING utf8) LIKE '%sibee%' OR CONVERT(image_size USING utf8) LIKE '%sibee%' OR CONVERT(orig_size USING utf8) LIKE '%sibee%' OR CONVERT(updates USING utf8) LIKE '%sibee%' OR CONVERT(updated USING utf8) LIKE '%sibee%' OR CONVERT(trace USING utf8) LIKE '%sibee%' OR CONVERT(attachment_id USING utf8) LIKE '%sibee%' OR CONVERT(resize USING utf8) LIKE '%sibee%' OR CONVERT(converted USING utf8) LIKE '%sibee%' OR CONVERT(level USING utf8) LIKE '%sibee%' OR CONVERT(pending USING utf8) LIKE '%sibee%' OR CONVERT(backup USING utf8) LIKE '%sibee%')

Sibeesh Venu
  • 18,755
  • 12
  • 103
  • 140
0

Another option (depending on the use case) would be to use DataMystic's TextPipe and DataPipe products. I've used them in the past, and they've worked great in the complex replacement scenarios, and without having to export data out of the database for find-and-replace.

Ville
  • 4,088
  • 2
  • 37
  • 38
  • Snobby admins (the same people who would tell users "RTFM" on the UNIX forums of the old) vote viable answers down. This is a perfectly fine solution to specific use-cases where dumping/restoring the whole database is not an option and the search/replace operation is complex enough so that it cannot be accomplished with straightforward SQL (or where the required SQL exceeds the user's capability). At least post your complaint with an answer if you vote it down! – Ville Aug 07 '19 at 02:56
0

I just wanted to share how I did this find/replace thing with sql database, because I needed to replace links from Chrome's sessionbuddy db file.

  • So I exported sql database file as .txt file by using SQLite Database Browser 2.0 b1
  • Find/replace in notepad++
  • Imported the .txt file back on SQLite Database Browser 2.0 b1
Rudolph
  • 1,504
  • 1
  • 10
  • 11