Ответ 1
Вы можете использовать " REPLACE INTO" или " INSERT... ON DUPLICATE КЛЮЧЕВОЕ ОБНОВЛЕНИЕ". Я считаю, что второе - это то, что вы хотите, но бывают ситуации, когда REPLACE INTO удобен.
Очень часто я хочу запустить запрос для одного из моих пользователей, где я хочу, чтобы строка была сохранена и ассоциирована с этим пользователем в отношении 1 к 1. Поэтому скажем (это просто произвольный пример), что у меня есть таблица, в которой отслеживается пользовательский автомобиль, а также информация о машине. Каждый пользователь может иметь 0 или 1 автомобиль. Если у пользователя нет автомобиля, в нем нет записи для этого пользователя.
car table (опять же, пример): id, user_id, car_make, car_model
Итак, когда я обновляю эту таблицу, я всегда делаю что-то вроде этого (псевдокод):
result = SELECT * FROM cars WHERE user_id=5
if (num_rows(result)>0){
UPDATE cars SET car_make='toyota', car_model='prius' WHERE user_id=5
}else{
INSERT INTO cars (user_id, car_make, car_model) VALUES (5, 'toyota', 'prius')
}
Как я могу сделать это в одном элегантном утверждении, которое работает "атомарно"? Что произойдет, если в другом процессе строка будет удалена между операторами SELECT и UPDATE? Мой оператор UPDATE не будет работать, когда должен быть запущен оператор INSERT. И я чувствую, что мне нужно сделать два похожих (но разных) заявления, чтобы выполнить одно и то же! Мне нужна инструкция, которая заверит меня, что данные, которые я хочу, существуют в таблице, особенно когда мне нужна только одна строка, которая удовлетворяет моим требованиям. Например, это может быть что-то вроде этого (это, конечно, полностью сделано):
MAKE SURE A ROW IN cars WHERE user_id=5 IS SET WITH car_make='toyota', car_model='prius'
Таким образом, если user_id из 5 уже существует, он будет обновлен, иначе он будет вставлен. Кроме того, если я изменил требования, например, чтобы сказать, что каждый пользователь может иметь нуль или одну машину данного car_make, тогда я мог бы дополнительно указать, что:
MAKE SURE A ROW IN cars WHERE user_id=5 AND car_make='toyota' IS SET WITH car_model='prius'
Надеюсь, мой вопрос имеет смысл! Как я могу улучшить эту базовую операцию insert-if-not-found или update-if-found, которая возникает так часто? Спасибо за любую помощь!
Вы можете использовать " REPLACE INTO" или " INSERT... ON DUPLICATE КЛЮЧЕВОЕ ОБНОВЛЕНИЕ". Я считаю, что второе - это то, что вы хотите, но бывают ситуации, когда REPLACE INTO удобен.
От мой другой ответ:
Если вы хотите сделать это в одном выражении, я бы рекомендовал использовать синтаксис INSERT ... ON DUPLICATE KEY UPDATE
следующим образом:
INSERT INTO table (id, someothervalue) VALUES (1, 'hi mom')
ON DUPLICATE KEY UPDATE someothervalue = 'hi mom';
Начальный оператор INSERT
будет выполняться, если нет существующей записи с указанным значением ключа (либо первичный ключ, либо уникальный). Если запись уже существует, выполняется следующий оператор UPDATE
(someothervalue = 3
).
Это поддерживается во всех версиях MySQL. Для получения дополнительной информации см. Страницу Справочное руководство по MySQL для INSERT ... ON DUPLICATE KEY UPDATE
Это называется UPSERT (UPDATE или inSERT). Есть много вопросов, которые вы можете найти. См. Википедию
EDIT: MySQL 4.1+ поддерживает INSATE (INSert или updATE), который должен получить то же самое, если у вас есть первичный ключ. Руководство по MySQL
Мне кажется, что проще переключить его. Попробуйте вставить, а затем обновить.
У MySQL есть специальное предложение "ON DUPLICATE KEY"
INSERT INTO cars (поля) VALUES (значения) ON DUPLICATE KEY UPDATE...
Это, конечно, требует, чтобы у вас были настройки уникальных ключей.
В Oracle у вас Merge.
Не знаю на MySql, но этот термин может дать вам что-то еще для поиска.
пример того, как я использовал ON DUPLICATE KEY UPDATE: INSERT INTO (имя, значение) VALUES (' ". $Key." ', ' ". $Val." ') ON DUPLICATE KEY UPDATE value = ' ". $Val." ' "