5

I have a table with fields foreign_key_id | value1 | value2, and I want to update value2 if I have a match for foreign_key_id and value1.

If foreign_key_id or value1 do not exist, I want to insert a new row. Is there a better way to do this than having PHP use a select statement and then branching to either an update or insert?

Edit: value2 can be the same value as in the database, so I cannot run and update, see if affected_rows is 0, and run and insert if it is.

2
  • Is foreign_key_id unique or primary? What version of MySQL? Commented May 29, 2011 at 16:37
  • I currently don't have it set as a key. Neither foreign_key_id nor value1 are unique. MySQL is v5.1.36. Commented May 29, 2011 at 16:39

4 Answers 4

8

Try using an IF EXISTS to determine whether to execute an UPDATE or an INSERT statement. You can do this in one PHP statement/query.

IF EXISTS(SELECT 1 FROM Mytable WHERE foreign_key_id = f1 AND value1 = v1)
BEGIN
    UPDATE Mytable SET value2 = v2
    WHERE foreign_key_id = f1 AND value1 = v1;
END
ELSE
BEGIN
      INSERT INTO Mytable(foreign_key_id,value1,value2)
      VALUES (f1,v1,v2);
END IF;
Sign up to request clarification or add additional context in comments.

2 Comments

Great. Thanks for this answer. Its useful to me too.
Do I need an extension to run this code in MySQL? It's not working for me, and IF EXISTS(SELECT 1 FROM Mytable WHERE foreign_key_id = f1 AND value1 = v1) END IF; isn't working either.
4

Yes, you can just run the update, then get the number of affected rows. If this is 0, run the insert. That will save you a select, because it is included in the update.

[edit]

Query as posted in the comments. Insert using select. This will save an select upfront. You can use mysql_affected_rows to get the number of rows inserted. If it returns 0, you can update. It actually contains the select, so I'm not sure if it is fasters (mysql and subselects aren't exactly friends). It will save you a roundtrip to the database however, and that might just make up for that.

insert into yourtable(f1, f2, fr) 
select 'value1', 'value2', 'value3' 
from dual /* yeah, I'm an Oracle dude */
where 
  not exists (
      select 'x' 
      from yourtable 
      where f1 = 'value1' and f2 = 'value2')

5 Comments

I cannot do that, because value2 can be the same value before as after, which will create a duplicate row. I'll edit my post to reflect this information.
In that case, you can use the program block in the other answer, or you can use the REPLACE statement. Replace is like INSERT, but it replaces a record if it already exists. dev.mysql.com/doc/refman/5.0/en/replace.html Not sure if this is exactly what you want. Didn't know about replace until just now. ;)
I cannot use replace because neither key is unique -- only the combination of foreign_key_id and value1 is unique
Well, in that case there are not many other solutions. You can use a select for insert insert into yourtable(f1, f2, fr) select 'value1', 'value2', 'value3' where not exists (select 'x' from yourtable where f1 = 'value1' and f2 = 'value2' That will save you a select. You can just update the database, and have this condition in the insert statement. But you'll have to try to see if it is faster.
Put the statement above in the answer for better readability.
1

Try this slight modification if you cannot get p.campbell's solution to work

IF EXISTS(SELECT 1 FROM Mytable WHERE foreign_key_id = f1 AND value1 = v1) THEN
    UPDATE Mytable SET value2 = v2
    WHERE foreign_key_id = f1 AND value1 = v1;
ELSE
    INSERT INTO Mytable(foreign_key_id,value1,value2)
    VALUES (f1,v1,v2);
END IF;

Comments

0

Best option: Use REPLACE instead of INSERT or UPDATE. It depends on the use of a primary key or unique key.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.