17

Very often, I want to run a query on one of my users where I want a row stored and associated with that user, in a 1-to-1 relationship. So let's say (this is just an arbitrary example), that I have a table that keeps track of a user's car, along with some info about the car. Each user can have either 0 or 1 cars. If the user has no car, there is no entry in the table for that user.

cars table (again, just an example): id, user_id, car_make, car_model

So, when I update this table, I always end up doing something like this (pseudo-code):

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')
}

How can I make this into one elegant statement that works "atomically"? What happens if, in another process, the row is REMOVED between the SELECT and UPDATE statements? My UPDATE statement will fail where the INSERT statement should have run. And I feel like I need to do two similar (but different) statements to accomplish the same thing! What I need is some statement that will assure me that the data I want exists in the table, especially when I only want 1 row that satisfies my requirement. For example, it might be something like (this is totally made-up of course):

MAKE SURE A ROW IN cars WHERE user_id=5 IS SET WITH car_make='toyota', car_model='prius'

That way, if user_id of 5 exists already, it will be updated, otherwise, it will be inserted. Also, if I changed the requirements, for example to say that each user can have zero or one cars of a given car_make, then I could further specify that:

MAKE SURE A ROW IN cars WHERE user_id=5 AND car_make='toyota' IS SET WITH car_model='prius'

I hope my question makes sense! How can I improve this basic insert-if-not-found or update-if-found operation that comes up so often? Thanks for any help!

4

7 回答 7

17

您可以使用“ REPLACE INTO ”或“ INSERT... ON DUPLICATE KEY UPDATE ”。我相信第二个是你想要的,但有些情况下 REPLACE INTO 很方便。

于 2009-04-18T15:12:53.177 回答
7

我的其他堆栈溢出答案

如果您想在单个语句中执行此操作,我建议使用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

于 2009-06-25T02:26:14.700 回答
3

这称为 UPSERT(UP日期或在SERT中)。您可以搜索许多关于它的 SO 问题。见维基百科

编辑: MySQL 4.1+ 支持 INSATE (INS ert 或 upd ATE),只要你有一个主键,它应该能让你得到同样的东西。MySQL 手册

于 2009-04-18T15:12:15.017 回答
1

我认为它更容易切换它。尝试插入,然后更新。

MySQL 特别有一个子句'ON DUPLICATE KEY'

在重复键更新时插入汽车(字段)值(值)...

这当然需要您设置正确的唯一键。

于 2009-04-18T15:13:29.117 回答
0

In Oracle you have Merge.

No idea on MySql, but the term might give you something else to search.

于 2009-04-18T15:08:29.490 回答
0

我如何使用 ON DUPLICATE KEY UPDATE 的示例: INSERT INTO registry (name, value) VALUES ('" . $key . "', '" . $val . "') ON DUPLICATE KEY UPDATE value= '" . $ val . "'"

于 2009-04-18T15:16:53.603 回答
0

将您的列属性设置为 UNIQUE,否则会重复输入。

于 2021-12-03T13:32:22.363 回答