2009-12-23 5 views
28

У меня есть стол с колонками record_id (auto inc), sender, sent_time и status.Как вставить запись или UPDATE, если она уже существует?

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

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

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

В противном случае я бы выполнить UPDATE заявление.

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

ответ

45

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

INSERT INTO table (key,col1) VALUES (1,2) 
    ON DUPLICATE KEY UPDATE col1 = 2; 
+2

синтаксиса является еще более мощным, чем: «ON KEY UPDATE DUPLICATE col1 = VALUES (col1) является более элегантным способом сделайте то, что вы описали (и оно работает с многострочными вставками). Вы также можете использовать значение col1, как в ON DUPLICATE KEY UPDATE col1 = col1 + 1. – ojrac

+0

Почему вы делаете col1 = col1 + 1. Что это значит mean? –

+1

Наткнулся на эту тему ... col1 = col1 +1 - пример, где, возможно, у вас есть счет в вашей таблице, вместо того, чтобы использовать SELECT для получения значения и добавить 1, он будет ссылаться на текущее значение в таблице, и выполнить вычисление, делающее вывод SELECT избыточным. – tutts

1

Один опции используется на дубликата синтаксиса обновления

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

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

3

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

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

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); 
11

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

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

Синтаксис в основном такой же, как 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

Ну, удаление старой строки вызовет осложнения, когда th e row является родительским элементом многих других таблиц. Те, у кого есть каскадное удаление, удаляют все отношения. Мы просто хотим обновить. –

0
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); 
Смежные вопросы