20

In my database I have a lot of users who've misspelled their e-mail address. This in turn causes my postfix to bounce a lot of mails when sending the newsletter.
Forms include (but are not limited to) "yaho.com", "yahho .com" etc.
Very annoying!

So i have been trying to update those record to the correct value.
After executing select email from users where email like '%@yaho%' and email not like '%yahoo%'; and getting the list, I'm stuck because I do not know how to update only the yaho part. I need the username to be left intact.

So I thought I would just dump the database and use vim to replace, but I cannot escape the @ symbol..

BTW, how do I select all email addresses written in CAPS? select upper(email) from users; would just transform everything into CAPS, whereas I just needed to find out the already-written-in-CAPS mails.

Matt
  • 22,721
  • 17
  • 71
  • 112
w00t
  • 616
  • 3
  • 9
  • 16
  • 3
    If you require valid e-mail addresses, can you add an e-mail verification upon registration? You can't guarantee that changing bob@yaho.com to bob@yahoo.com will actually reach your registered user, nor that it will not also produce a bounce. – David Fox May 26 '10 at 14:33
  • Indeed you're right, I also thought that any sane person should add validation. But I'm just the sysadmin over here and I thought to address the situation from my side. Will have to submit a bug or smth. – w00t May 26 '10 at 15:08

6 Answers6

45

You may want to try something like the following:

UPDATE   users
SET      email = CONCAT(LEFT(email, INSTR(email, '@')), 'yahoo.com')
WHERE    email LIKE '%@yaho.com%';

Test case:

CREATE TABLE users (email varchar(50));

INSERT INTO users VALUES ('test1@yahoo.com');
INSERT INTO users VALUES ('test2@yaho.com');
INSERT INTO users VALUES ('test3@yahoo.com');


UPDATE   users
SET      email = CONCAT(LEFT(email, INSTR(email, '@')), 'yahoo.com')
WHERE    email LIKE '%@yaho.com%';

Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0


SELECT * FROM users;
+-----------------+
| email           |
+-----------------+
| test1@yahoo.com |
| test2@yahoo.com |
| test3@yahoo.com |
+-----------------+
3 rows in set (0.00 sec)

To answer your second question, you probably need to use a case sensitive collation such as the latin1_general_cs:

SELECT * FROM users WHERE email COLLATE latin1_general_cs = UPPER(email);

Test case:

INSERT INTO users VALUES ('TEST4@YAHOO.COM');


SELECT * FROM users;   
+-----------------+
| email           |
+-----------------+
| test1@yahoo.com |
| test2@yahoo.com |
| test3@yahoo.com |
| TEST4@YAHOO.COM |
+-----------------+
4 rows in set (0.00 sec)


SELECT * FROM users WHERE email COLLATE latin1_general_cs = UPPER(email);
+-----------------+
| email           |
+-----------------+
| TEST4@YAHOO.COM |
+-----------------+
1 row in set (0.00 sec)
Daniel Vassallo
  • 337,827
  • 72
  • 505
  • 443
  • 2
    Great example! Worked without problems. One thing though, the database is UTF8 so I cannot use latin1 collations. But not a big deal, the SELECT isn't vital, I just updated everything to lowercase. Thank you! – w00t May 27 '10 at 11:23
  • I'm still coming back to this answer years later. – Captain Hypertext Jan 25 '17 at 17:40
  • I am trying to put @ in a varchar. But is says extranoues... How to enter email adresses in mysql? – Lealo Aug 16 '17 at 23:45
3
UPDATE users SET email = REPLACE( email, SUBSTRING_INDEX( email,  '@', -1 ) ,  CONCAT(user_id, 'domain.com' ) ) WHERE [MYSQL CONDITION];

To update live email address to test email address

Abdul Rehman
  • 689
  • 6
  • 11
2

To address your second question (about finding emails written in caps), something like this might be helpful:

select email from users where upper(email) = email

(Forgive me if the syntax is not precisely correct, since I'm used to DB2. The idea is to compare the straight email address with the upper-cased version.)

Syntactic
  • 10,721
  • 3
  • 25
  • 25
  • @Syntactic: Note that the default character set and collation in MySQL are case insensitive by default. [Source](http://dev.mysql.com/doc/refman/5.0/en/case-sensitivity.html) – Daniel Vassallo May 26 '10 at 14:48
  • @Daniel Vassallo Good point. Learning something new every day. – Syntactic May 26 '10 at 14:55
  • Oh I think I understand what you mean. But instead of finding UPPER mails, it returns all lower cased mails.. about 50.000 of them :)) Fair enough with the case insensitive, there is no problem with sending mails or anything else, it's just that it bothered my eyes. – w00t May 26 '10 at 15:15
  • 1
    @w00t: If you want to convert all the emails to lowercase, you can simply do: `UPDATE users SET email = lower(email);` – Daniel Vassallo May 26 '10 at 15:39
  • @w00t: Do it on the application side, when inserting/updating the data, and you won't have to worry about it again. – Syntactic May 27 '10 at 12:41
2
UPDATE contacts SET email = REPLACE(email, SUBSTRING_INDEX(email, '@', -1), 'domain.com')
Floern
  • 33,559
  • 24
  • 104
  • 119
phoenix
  • 1,629
  • 20
  • 11
1

You could try using INSTR together with SUBSTR or LEFT to get the part before the "@" symbol, perhaps.

Something like SELECT LEFT("foo@yaho.com",INSTR("foo@yaho.com","@")-1); seems to work.

CharlesLeaf
  • 3,201
  • 19
  • 16
1

For the first question, I would choose something like

UPDATE users
SET email = INSERT(email,INSTR(email,'@'), LENGTH(email), '@yahoo.com')
WHERE email LIKE '%@yaho.com'

Just for the sake of being thorough, this is multi-byte safe even though I've used LENGTH. All that's needed is for the third argument of INSERT to be at least as large as the end of the substring.

Syntactic's answer of finding the all-caps email is a good answer. Possibly performing slightly faster, although you would likely not notice the difference, is

SELECT email FROM users WHERE BINARY(email) NOT REGEXP '[a-z]'

Update: BINARY(email) is needed to force case-sensitive matching.

David M
  • 4,325
  • 2
  • 28
  • 40
  • 1
    I think you need to wrap the `@` in single quotes in the `INSTR()` function, otherwise it will return `NULL`. Also I guess your last query should look something like `FROM users WHERE email NOT REGEXP ...`. – Daniel Vassallo May 26 '10 at 15:00
  • 1
    Indeed, the `@` needed single quotes because it returned `NULL`. It worked after. The second query matches only emails that are made of numbers or +--_ but no alphabetical ones. – w00t May 27 '10 at 11:29