很多时候,我想对我的一个用户运行查询,我希望在其中存储一行并与该用户以一对一的关系关联。 假设(这只是一个任意的例子),我有一个表来跟踪用户的汽车,以及有关汽车的一些信息。 每个用户可以拥有 0 或 1 辆汽车。 如果用户没有汽车,则表中没有该用户的条目。
cars 表(同样,只是一个例子):
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 语句应该运行的地方失败。 我觉得我需要做两个相似(但不同)的陈述来完成同样的事情! 我需要的是一些语句来确保我想要的数据存在于表中,特别是当我只想要满足我的要求的 1 行时。 例如,它可能是这样的(当然这完全是编造的):
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'
我希望我的问题有意义! 如何改进这种经常出现的基本“如果未找到则插入”或“如果找到则更新”操作? 谢谢你的帮助!
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!
发布评论
评论(7)
您可以使用“替换为”或“插入...重复密钥更新”。 我相信第二个就是你想要的,但在某些情况下 REPLACE INTO 很方便。
You can use "REPLACE INTO" or "INSERT… ON DUPLICATE KEY UPDATE". I believe the second is what you want, but there are situations where REPLACE INTO is convenient.
来自我的其他 Stack Overflow 答案 :
如果您想在单个语句中执行此操作,我建议使用
INSERT ... ON DUPLICATE KEY UPDATE
语法,如下所示:初始
INSERT
语句将执行如果不存在具有指定键值(主键或唯一键)的现有记录。 如果记录已存在,则执行以下UPDATE
语句 (someothervalue = 3
)。所有版本的 MySQL 都支持此功能。 有关详细信息,请参阅 MySQL 参考手册页面 <代码>插入...重复密钥更新
From my other Stack Overflow answer:
If you want to do this in a single statement, I would recommend using the
INSERT ... ON DUPLICATE KEY UPDATE
syntax, as follows:The initial
INSERT
statement will execute if there is no existing record with the specified key value (either primary key or unique). If a record already exists, the followingUPDATE
statement (someothervalue = 3
) is executed.This is supported in all versions of MySQL. For more info, see the MySQL Reference Manual page for
INSERT ... ON DUPLICATE KEY UPDATE
这称为 UPSERT(UP日期或SERT)。 有很多关于它的问题,你可以搜索一下。 请参阅维基百科
编辑: MySQL 4.1+ 支持 INSATE( INSert 或 updATE),只要您有主键,这应该会得到相同的结果。 MySQL 手册
This is called an UPSERT (UPdate or inSERT). There are a number of SO questions about it you can search for. See Wikipedia
EDIT: MySQL 4.1+ supports INSATE (INSert or updATE), which should get you the same thing, as long as you have a primary key. MySQL Manual
我认为转换它更容易。 尝试插入,然后更新。
MySQL 特别有一个子句 'ON DUPLICATE KEY'
INSERT INTO cars (fields) VALUES (values) ON DUPLICATE KEY UPDATE ...
这当然要求您有正确的唯一键设置。
I think it's easier to switch it around. Try to insert, then update.
MySQL specifically has a clause 'ON DUPLICATE KEY'
INSERT INTO cars (fields) VALUES (values) ON DUPLICATE KEY UPDATE ...
This of course requires you to have proper unique keys setup.
我如何使用重复密钥更新的示例:
INSERT INTO 注册表(名称,值)VALUES ('" . $key . "', '" . $val . "') ON DUPLICATE KEY UPDATE value= '" . $val . "'"
an example of how I have used ON DUPLICATE KEY UPDATE:
INSERT INTO registry (name, value) VALUES ('" . $key . "', '" . $val . "') ON DUPLICATE KEY UPDATE value= '" . $val . "'"
在 Oracle 中,您有合并。
对 MySql 不了解,但该术语可能会给您提供其他搜索内容。
In Oracle you have Merge.
No idea on MySql, but the term might give you something else to search.
将列属性设置为“唯一”,否则将生成重复条目。
Set your column attributes to UNIQUE, otherwise will make a duplicate entry.