У меня была ситуация, когда мне нужно было обновить или вставить в таблицу в соответствии с двумя полями (оба внешних ключа), для которых я не мог установить ограничение UNIQUE (поэтому INSERT ... ON DUPLICATE KEY UPDATE не сработает). Вот что я в итоге использовал:
replace into last_recogs (id, hasher_id, hash_id, last_recog)
select l.* from
(select id, hasher_id, hash_id, [new_value] from last_recogs
where hasher_id in (select id from hashers where name=[hasher_name])
and hash_id in (select id from hashes where name=[hash_name])
union
select 0, m.id, h.id, [new_value]
from hashers m cross join hashes h
where m.name=[hasher_name]
and h.name=[hash_name]) l
limit 1;
Этот пример взят из одной из моих баз данных, при этом входные параметры (два имени и номер) заменены на [hasher_name], [hash_name] и [new_value]. Вложенный SELECT ... LIMIT 1 извлекает первую из существующей записи или новой записи (last_recogs.id - это первичный ключ с автоинкрементом) и использует это как значение, вводимое в REPLACE INTO.