Как ВСТАВИТЬ запись или ОБНОВЛЕНИЕ, если это уже существует? - PullRequest
31 голосов
/ 23 декабря 2009

У меня есть таблица со столбцами record_id (auto inc), sender, sent_time и status.

В случае отсутствия какой-либо записи конкретного отправителя, например, «sender1», я должен ВСТАВИТЬ новую запись, в противном случае мне нужно ОБНОВИТЬ существующую запись, которая принадлежит «user1».

Так что, если запись еще не сохранена, я бы выполнил

# record_id is AUTO_INCREMENT field
INSERT INTO messages (sender, sent_time, status)
VALUES (@sender, time, @status)

В противном случае я выполняю инструкцию UPDATE.

В любом случае ... кто-нибудь знает, как объединить эти два оператора для вставки новой записи, если нет записи, для которой значение отправителя поля равно "user1", иначе обновите существующую запись?

Ответы [ 6 ]

47 голосов
/ 23 декабря 2009

MySQL поддерживает синтаксис insert-on-duplicate , f.e.:

INSERT INTO table (key,col1) VALUES (1,2)
  ON DUPLICATE KEY UPDATE col1 = 2;
12 голосов
/ 23 декабря 2009

Если у вас есть твердые ограничения для таблицы, то вы также можете использовать для этого REPLACE INTO. Вот цитата из MySQL:

REPLACE работает точно так же, как INSERT, за исключением того, что если старая строка в таблице имеет то же значение, что и новая строка для PRIMARY KEY или UNIQUE индекса, старая строка удаляется перед вставкой новой строки.

Синтаксис в основном такой же, как INSERT INTO, просто замените INSERT на REPLACE.

INSERT INTO messages (sender, sent_time, status) VALUES (@sender, time, @status)

тогда будет

REPLACE INTO messages (sender, sent_time, status) VALUES (@sender, time, @status)

Обратите внимание, что это специфичная для MySQL команда, которая отсутствует в других БД, поэтому помните о переносимости.

3 голосов
/ 23 декабря 2009

Как уже упоминали другие, вы должны использовать «вставить ... при обновлении дубликата ключа», иногда называемый «upsert». Однако в вашем конкретном случае вы не хотите использовать статическое значение в обновлении, а скорее значения, которые вы передаете предложению values ​​оператора вставки.

В частности, я думаю, что вы хотите обновить два столбца, если строка уже существует:

1) sent_time
2) status

Чтобы сделать это, вы должны использовать выражение «upsert», подобное этому (на вашем примере):

INSERT INTO messages (sender, sent_time, status) 
VALUES (@sender, time, @status)
ON DUPLICATE KEY UPDATE 
  sent_time = values(sent_time),
  status = values(status);
2 голосов
/ 23 декабря 2009

Проверить «Вставить при обновлении дубликата ключа» .

INSERT INTO table (a,b,c) VALUES (1,2,3)
  ON DUPLICATE KEY UPDATE c=c+1;

UPDATE table SET c=c+1 WHERE a=1;
1 голос
/ 23 декабря 2009

Один из вариантов использует дублирующий синтаксис обновления

http://dev.mysql.com/doc/refman/5.1/en/insert-on-duplicate.html

Другие опции делают select, чтобы выяснить, существует ли запись, а затем соответственно вставьте / обновите. Имейте в виду, что если вы удерживаете транзакцию, выбор не приведет к явному завершению транзакции, поэтому ее безопасно использовать.

0 голосов
/ 05 июля 2013
use merge statement :

merge into T1
          using T2
          on (T1.ID = T2.ID)
    when  matched
    then  update set  
                      T1.Name = T2.Name
    when  not matched
    then  insert values (T2.ID,T2.Name);
...